반응형
- 본 내용은 Linux (Ubuntu 14.04 lts)를 기반으로 제작되었습니다. -
I/O Multiplexing Select 개념 및 예제 코드 :: http://www.crocus.co.kr/542
I/O Multiplexing Select를 이용하여 간단한 에코 서버를 제작하는 방법이다.
클라이언트에서 메시지를 보내면 서버가 그 메시지를 확인하고,
select에 의해 감지되면 메시지를 복사하여 다시 클라이언트로 보내주는 방식이고,
5초동안 아무런 일이 없으면 Time Out이라고 서버에 출력해주는 방식을 취한다.
소스 코드 :
<header.h>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //header.h #include <stdio.h> #include <string.h> #include <stdlib.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/select.h> #define PORT 20162 #define BUFFER_SIZE 100 #define LISTEN_QUEUE_SIZE 5 // This source code Copyright belongs to Crocus // If you want to see more? click here >> | Crocus |
<select.c>
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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | #include "header.h" int main(int argc, char* argv[]) { int listenFD, connectFD; struct sockaddr_in listenSocket, connectSocket; struct timeval timeout; // reads, cpyReads 생성 // 이때 cpyReads는 while에서 reads의 복제를 위해 이용 fd_set reads, cpyReads; socklen_t addrSz; // address size를 구할 변수 int fdMax, strLen, fdNum, i; char buf[BUFFER_SIZE]; //if (argc != 2) //{ // printf("Usage : %s <port>\n", argv[0]); // exit(1); //} listenFD = socket(PF_INET, SOCK_STREAM, 0); memset(&listenSocket, 0, sizeof(listenSocket)); listenSocket.sin_family = AF_INET; listenSocket.sin_addr.s_addr = htonl(INADDR_ANY); listenSocket.sin_port = htons(PORT); if (bind(listenFD, (struct sockaddr *) &listenSocket, sizeof(listenSocket)) == -1) { printf("Can not bind.\n"); return -1; } if (listen(listenFD, LISTEN_QUEUE_SIZE) == -1) { printf("Listen fail.\n"); return -1; } FD_ZERO(&reads); // 소켓 셋 초기화 FD_SET(listenFD, &reads); // listenFD 소켓 셋 1로 설정 fdMax = listenFD; // 소켓 마지막 번호를 받아온다 while (1) { cpyReads = reads; // 복제 timeout.tv_sec = 5; // 5초 timeout.tv_usec = 0; if ((fdNum = select(fdMax + 1, &cpyReads, 0, 0, &timeout)) == -1) // 타임아웃은 5초로 지정한다. break; // select 실패시 if (fdNum == 0) // select의 return값이 0이면 즉, 타임아웃이면 서버 창에 timeout 출력 후 진행 { printf("Time Out!\n"); continue; } for (i = 0; i < fdMax + 1; i++) { if (FD_ISSET(i, &cpyReads)) // fd가 켜져있다면 { if (i == listenFD) // 그때 i가 FD와 같다면 { addrSz = sizeof(connectSocket); connectFD = accept(listenFD, (struct sockaddr*)&connectSocket, &addrSz); FD_SET(connectFD, &reads); // reads 소켓 셋에 connectFD를 부분을 1로 바꾼다 if (fdMax < connectFD) fdMax = connectFD; printf("connected client : %d\n", connectFD); } else { strLen = read(i, buf, BUFFER_SIZE); // close request if (strLen == 0) { FD_CLR(i, &reads); // 0으로 지운다 close(i); printf("close client : %d\n", i); } else { // echo write(i, buf, strLen); } } } } } close(listenFD); return 0; } // This source code Copyright belongs to Crocus // If you want to see more? click here >> | Crocus |
<client.c>
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 | //client.cpp # include "header.h" int main(int argc, char** argv) { if (argc != 2) { printf("Usage: %s IPv4-address\n", argv[0]); return -1; } struct sockaddr_in connectSocket; memset(&connectSocket, 0, sizeof(connectSocket)); connectSocket.sin_family = AF_INET; inet_aton(argv[1], (struct in_addr*) &connectSocket.sin_addr.s_addr); connectSocket.sin_port = htons(PORT); int connectFD = socket(AF_INET, SOCK_STREAM, 0); if (connect(connectFD, (struct sockaddr*) &connectSocket, sizeof(connectSocket)) == -1) { printf("Can not connect.\n"); return -1; } else { int readBytes, writtenBytes; char sendBuffer[BUFFER_SIZE]; char receiveBuffer[BUFFER_SIZE]; while(1) { //서버에 문자열을 보낸 뒤 서버가 보낸 echo를 받아 출력. printf("input :: "); fgets(sendBuffer,BUFFER_SIZE,stdin); write(connectFD, sendBuffer, strlen(sendBuffer)); readBytes = read(connectFD, receiveBuffer, BUFFER_SIZE); printf("%d bytes read\n", readBytes); receiveBuffer[readBytes] = '\0'; fputs(receiveBuffer, stdout); fflush(stdout); } } close(connectFD); return 0; } // This source code Copyright belongs to Crocus // If you want to see more? click here >> | Crocus |
반응형
'Applied > Network' 카테고리의 다른 글
네트워크 통신 프로그래밍 용어 및 설명 정리 - (1) (0) | 2016.12.08 |
---|---|
소켓 프로그래밍 - (28) I/O Multiplexing Poll 개념 및 소스 코드 (0) | 2016.11.20 |
소켓 프로그래밍 - (26) I/O Multiplexing Select 개념 및 소스코드 (0) | 2016.11.20 |
[부록] 두 수를 입력받아 더하는 서버 클라이언트 통신 (0) | 2016.11.17 |
소켓 프로그래밍 - (25) 세마포어(Semaphore)를 이용한 멀티 스레드 통신 (0) | 2016.11.17 |