TCP socket library 만들기 [다섯번째] : 최종테스트 및 소스첨부
자, 이번 시간에는 지금까지 만든 tcp library 를 이용하여 사용자 메시지까지 주고받아보겠습니다.
정말 설레지 않나요 ? 나만 설렌가...;;;
자신이 만든 코드를 시험하기전 기대하는 마음이 드는건 참 즐거운 일입니다. ^^
다음은 지금까지 만든 파일 List 입니다. 파일은 아직 몇개 안되니 주석을 보시면 어떤 파일인지 아실겁니다.
sh> ls -al total 32 drwxrwxr-x 3 bitmyer bitmyer 4096 Nov 30 03:57 ./ drwxrwxr-x. 14 bitmyer bitmyer 4096 Nov 25 10:25 ../ -rw-rw-r-- 1 bitmyer bitmyer 2014 Nov 30 03:57 Makefile // library makefile -rw-rw-r-- 1 bitmyer bitmyer 3460 Nov 30 03:40 socket_base.cpp // socket_base 함수구현 -rw-rw-r-- 1 bitmyer bitmyer 947 Nov 30 03:29 socket_base.h // socket_base class 정의 -rw-rw-r-- 1 bitmyer bitmyer 2418 Nov 30 03:03 tcp_socket.cpp // tcpsvr, tcpcli 함수구현 -rw-rw-r-- 1 bitmyer bitmyer 564 Nov 30 02:33 tcp_socket.h // tcpsvr, tcpcli class 정의 drwxrwxr-x 2 bitmyer bitmyer 4096 Nov 30 05:10 test/ sh> ls -al test/* -rw-rw-r-- 1 bitmyer bitmyer 726 Nov 30 03:57 test/Makefile // test binary makefile -rw-rw-r-- 1 bitmyer bitmyer 589 Nov 30 03:41 test/tcpcli.cpp // tcp client program -rw-rw-r-- 1 bitmyer bitmyer 1595 Nov 30 03:28 test/tcpsvr.cpp // tcp server program
아래가 tcpcli.cpp 코드입니다.
buffer 에 메시지 넣고 cli->send() 함수를 호출하는 부분이 추가되었습니다.
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <tcp_socket.h> int main() { int i; int ret; int sock; char buf[64]; tcpcli * cli = new tcpcli(1,0,0); sock = cli->connect( (char *)"127.0.0.1", 11111 ); if( sock < 0 ) exit(1); printf("open okay...[%d]n", sock); memset(buf, 0x00, sizeof(buf)); for(i=0; i<10; i++) { sprintf(buf, "this is [%d]th test message !!!!", i); ret = cli->send(buf, strlen(buf)); printf("send... ret (%d)n", ret); } // sleep here return 0; }
다음은 tcpsvr.cpp 코드입니다.
마찬가지로 buf 선언 후 accept socket 에 대해 event 가 발생하면 svr->recv() 함수를 호출하여 데이터를 읽어들이는 부분이 추가되었습니다.
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <tcp_socket.h> int main() { int ret; int sock = -1; int accept_sock = -1; struct timeval timeout; fd_set fd; char buf[64]; tcpsvr * svr = new tcpsvr(1,1,0); // tcpsvr 객체 생성 (socket option 값 지정) // server socket 준비 및 listen sock = svr->open( 11111 ); if( sock < 0 ) exit(1); printf("open okay...[%d]n", sock); memset(buf, 0x00, sizeof(buf)); while(1) { // event 가 없을 경우 select 에서 기다려줄 시간 (timeout) timeout.tv_sec = 1; timeout.tv_usec = 0; FD_ZERO(&fd); if( sock > 0 ) FD_SET( sock, &fd ); // listen socket 을 fdset 에 셋팅 if( accept_sock > 0 ) FD_SET( accept_sock, &fd ); // 데이터 수신 socket 셋팅 // select 를 통해 fdset 에 설정된 FD 에 대해 Event 감시 if( (ret = select( FD_SETSIZE, &fd, NULL, NULL, &timeout)) <= 0 ) { // timeout 이나 error 이면 잠깐 쉬었다가 다시 시도 // sleep here continue; } // sock (listen socket) 에 Event 가 감지되었을 경우 if( FD_ISSET( sock, &fd ) ) { // 만약 이전의 accept_sock 이 남아있는 듯하면 확인사살로 close 하고 초기화 if( accept_sock > 0 ) { close(accept_sock); accept_sock = -1; } // listen socket 에 있는 pending 연결요청을 하나 받아들인다. accept_sock = svr->accept(); if( accept_sock < 0 ) { printf("accept fail...[%d] [%s]n", accept_sock, strerror(errno)); // sleep here continue; } printf("accept okay...[%d]n", accept_sock ); } if( FD_ISSET( accept_sock, &fd ) ) { ret = svr->recv(buf); if( ret < 0 ) { svr->close(accept_sock); continue; } printf("recv... ret[%d] message[%s]n", ret, buf ); } } return 0; }
컴파일 순서는 library directory 에서 make 한 후 LD_LIBRARY_PATH 잡아주고, test directory 에서 make 하고 실행하면 됩니다.
자... 이제 실행해 봅시다.
두근두근.... ^^
먼저 tcpsvr 먼저 실행 후 tcpcli 를 띄우면 됩니다.
sh> ./tcpsvr open okay...[3] accept okay...[4] recv... ret[31] message[this is [0]th test message !!!!] recv... ret[31] message[this is [1]th test message !!!!] recv... ret[31] message[this is [2]th test message !!!!] recv... ret[31] message[this is [3]th test message !!!!] recv... ret[31] message[this is [4]th test message !!!!] recv... ret[31] message[this is [5]th test message !!!!] recv... ret[31] message[this is [6]th test message !!!!] recv... ret[31] message[this is [7]th test message !!!!] recv... ret[31] message[this is [8]th test message !!!!] recv... ret[31] message[this is [9]th test message !!!!]
sh> ./tcpcli open okay...[3] [0] send... ret (31) [1] send... ret (31) [2] send... ret (31) [3] send... ret (31) [4] send... ret (31) [5] send... ret (31) [6] send... ret (31) [7] send... ret (31) [8] send... ret (31) [9] send... ret (31)
아주 잘 동작하네요. 주고 받은 메시지 내용과 size 도 정확합니다.
이제 이 library 가 어느 정도의 성능을 보이고 응답 latency 가 얼마이고... 이런 것은 여러분이 직접 시험을 해보셨으면 좋겠네요.
clock_gettime() 이라는 함수를 사용하면 nano second 단위까지 시간을 정확하게 측정할 수 있습니다.
참고로 각기 다른 서버에서 client 가 자신이 송신한 메시지가 server 측에 갔다오는데 얼마나 걸리는지 정확하게 측정하고 싶다면, client 가 송신하는 메시지에 clock_gettime() 의 결과를 저장하여 보낸 후, server 는 이를 수신하는 즉시 그대로 client 에 전송해주면, client 는 메시지 수신 직후 다시 clock_gettime() 을 측정하여 메시지에 담긴 시간과의 차이를 구하면 됩니다.
이것이 해당 메시지가 1 round trip 을 하는데 걸린 정확한 시간이 되는 것이죠.
이제 소스 첨부를 마지막으로 tcp socket library 에 대한 강의를 마치겠습니다.
다음 시간부터는 inet udp library 를 만들어보도록 하겠습니다.
cfile26.uf.261D82505298FD3F249E97.gz
4번째 강의는 없나요?
제가 블로그 데이터를 한번 날려먹은 적이 있어요… ㅠㅜ
아마도 그 때 날아갔나봅니다. 죄송합니다…;;