(윤성우 저, 'TCP/IP 소켓 프로그래밍' - 4장 관련 내용입니다)
echo_client 코드가 주어질 때, 주어진 클라이언트의 IP Address와 Port 번호를 출력하는 Iterative Echo Server를 만드는 문제입니다.
아래는 echo_client 코드입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, char *argv[]) { int sock; char message[BUF_SIZE]; int str_len; struct sockaddr_in serv_adr; if(argc!=3) { printf("Usage : %s <IP> <port>\n", argv[0]); exit(1); } sock=socket(PF_INET, SOCK_STREAM, 0); if(sock==-1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=inet_addr(argv[1]); serv_adr.sin_port=htons(atoi(argv[2])); if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1) error_handling("connect() error!"); else puts("Connected..........."); while(1) { fputs("Input message(Q to quit): ", stdout); fgets(message, BUF_SIZE, stdin); if(!strcmp(message,"q\n") || !strcmp(message,"Q\n")) break; write(sock, message, strlen(message)); str_len=read(sock, message, BUF_SIZE-1); message[str_len]=0; printf("Message from server: %s", message); } close(sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } |
주어진 echo_client 코드에 맞는 echo_server를 구현하기 위해 아래와 같은 코드를 작성했습니다.
(코드에서 해당되는 모든 부분에 주석으로 설명을 달았습니다. 아래 코드를 보고 이해가 안 된다면 가장 위에 언급된 책 4장을 참고하시기 바랍니다.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | //헤더 부분입니다. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); //main함수 int main(int argc, char *argv[]) { int serv_sock, clnt_sock; //서버와 클라이언트 소켓을 저장할 변수 선언 char message[BUF_SIZE]; //메세지를 저장할 변수 선언 int str_len, i; //서버와 클라이언트 주소정보를 저장할 구조체 변수 선언 struct sockaddr_in serv_adr; struct sockaddr_in clnt_adr; socklen_t clnt_adr_sz; //입력값 올바르지 않다면 에러 if(argc!=2) { printf("Usage : %s <port>\n", argv[0]); exit(1); } //서버의 소켓을 생성 serv_sock=socket(PF_INET, SOCK_STREAM, 0); if(serv_sock==-1) error_handling("socket() error"); //서버의 주소정보를 저장, 이때 네트워크 바이트 순서로 저장한다 memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); serv_adr.sin_port=htons(atoi(argv[1])); //bind 함수를 통해 소켓에 서버의 주소정보를 할당 if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1) error_handling("bind() error"); //연결 대기 상태로 진입 if(listen(serv_sock, 5)==-1) error_handling("listen() error"); clnt_adr_sz=sizeof(clnt_adr); for(i=0; i<5; i++) { //클라이언트로 부터 연결 요청이 오면 수락한다. 이때 클라이언트의 주소 정보를 저장한다. clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); if(clnt_sock==-1) error_handling("accept() error"); else { /* 클라이언트의 IP를 출력하기 위해 구조체 clnt_adr의 인자 sin_addr에 저장된 IP주소를 참조. 이때 32비트 정수 자료형으로 저장 된 IP 주소를 네트워크 바이트 순서로 바꾸어 OOO.OOO.OOO.OOO 형태의 문자열로 출력하기 위해 inet_ntoa 함수를 이용한다. */ printf("Client's IP : %s\n",inet_ntoa(clnt_adr.sin_addr)); /* 클라이언트의 Port번호를 출력하기 위해 구조체 clnt_adr의 인자 sin_port에 저장된 Port번호를 참조. 이때 Big Endian 방식으로 저장 된 포트 번호를 네트워크 바이트 순서로 정렬해서 반환하기 위해 ntohs 함수를 이용한다. */ printf("Client's Port : %d\n",ntohs(clnt_adr.sin_port)); printf("Connected client %d \n", i+1); } //버퍼를 다 읽어와 이를 출력한다. 클라이언트가 종료 요청시에 while문을 탈출한다. while((str_len=read(clnt_sock, message, BUF_SIZE))!=0) write(clnt_sock, message, str_len); //클라이언트 소켓의 종료를 받아들인다. close(clnt_sock); } //서버 소켓의 종료 close(serv_sock); return 0; } //에러 처리 void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } |
'학교 수업 및 과제 > 컴퓨터 네트워크' 카테고리의 다른 글
3. I/O 멀티플렉싱 서버와 멀티프로세스 클라이언트를 이용한 채팅 프로그램 (0) | 2018.05.28 |
---|---|
2. Select 함수를 사용하는 I/O 멀티플렉싱 에코 클라이언트 작성 (0) | 2018.05.28 |