책/윤성우 TCPIP

멀티 플렉싱 서버의 구현 지금 까지 익혀온 select 함수의 사용법을 바탕으로 멀티 플렉싱 서버를 구현할 차례이다. 다음예제는 멀티플렉싱 기반의 에코 서버이다. echo_selectserv.c #include #include #include #include #include #include #include #include #define BUF_SIZE 100 void error_handling(const char *buf); int main(int argc, char *argv[]) { int serv_sock, clnt_sock; struct sockaddr_in serv_adr, clnt_adr; struct timeval timeout; fd_set reads, cpy_reads; socklen_t..
최종 select 함수를 호출하는 예제의 확인 select.c #include #include #include #include #define BUF_SIZE 30 int main(int argc, char argv[]) { fd_set reads, temps; int result, str_len; char buf[BUF_SIZE]; struct timeval timeout; // 14 // 다소 복잡해 보이지만 아주 쉬운 예제다 일단 이 라인에서 fd_set형 변수를 // 초기화하고 아래에서 파일 디스크립터 0의 위치를 1로 설정해 주고 있다. // 즉 표준 입력에 변화가 있는지 관심을 두고 보겠다는 뜻이다. FD_ZERO(&reads); FD_SET(0, &reads); // 0 is standard ..
검사(관찰)의 범위지정과 타임아웃의 설정 select함수 #include #include int select( int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout); -> 성공시 0 이상 실패시 -1 반환 maxfd : 검사 대상이되는 파일 디스크립터의 수 readset : fd_set형 변수에 "수신된 데이터의 존재여부"에 관심 있는 파일 디스크립터 정보를 모두 등록해서 그 변수의 주소 값을 전달한다 . writeset : fd_set형 변수에 "블로킹 없는 데이터 전송의 가능여부"에 관심있는 파일 디스크립터 정보를 모두 등록해서 그 변수의 주소값을 전달한다. exceptset : fd..
12 IO 멀티플렉싱(Multiplexing) 12-1 IO멀티 플렉싱 기반의 서버 멀티프로세스 서버의 단점과 대안 이전 Chapter에서는 다중접속 서버의 구현을 위해서 클라이언트의 연결 요청이 있을 때마다 새로운 프로세스를 생성하였다. 이는 실제 사용되는 방법이지만 문제가 전혀 없는 방법은 아니다 프로세스의 생성에는 상당히 많은 대가를 지불해야 하기 때문이다. 많은 양의 연산이 요구되며 필요한 메모리 공간도 비교적 큰 편이다. 또한 프로세스마다 별도의 메모리 공간을 유지하기 때문에 상호간에 데이터를 주고받으려면 다소 복잡한 방법을 택할 수 밖에 없다(IPC는 다소 복잡한 통신방법이다) ᅟIPC가 필요한 상황에서는 프로그래밍하기가 상대적으로 까다로워진다는 것을 여러분도느끼지 않았는가? " 그렇다면 대안..
pipe3.c 예제 #include #include #define BUF_SIZE 30 int man(int argc, char *argv[]) { int fds1[2], fds2[2]; char str1[] = "Who are you?"; char str2[] = "Thank you for your message"; char buf[BUF_SIZE]; pid_t pid; // 두 개의 파이프를 생성하고 있다. pipe(fds1), pipe(fds2); pid = fork(); if(pid == 0) { // 자식 프로세스에서 부모 프로세스로의 데이터 전송은 배열 fds1이 참조하는 // 파이프를 통해서 이뤄진다. write(fds1[1],str1, sizeof(str1)); read(fds2[0], b..
이번에는 하나의 파이프를 통해서 두 프로세스가 양방향으로 데이터를 주고 받는 예제를 작성해보고자한다. 이예제에는 보이고자 하는 통신방식은 다음과 같다. 위그림과 같이 하나의 파이프를 대상으로 양방향으로 통신을 하는 것도 물론 가능하다 하지만이러한 모델로 구현할 경우 몇 배는 더 주의해야한다. pipe2.c 예제 #include #include #define BUF_SIZE 30 int main(int argc, char *argv[]) { int fds[2]; char str1[] = "Who are you"; char str2[] = "Thank you for your message"; char buf[BUF_SIZE]; pid_t pid; // pipe 함수호출을 통해서 파이프를 생성하고 있다. //..
11 프로세스간 통신 (Inter Process Communication) 11- 01 프로세스간 통신의 기본 개념 프로세스간 통신의 기본 이해 프로세스간 통신은 생각보다 어렵지 않은 개념이다. 프로세스 A가 프로세스 B에게 다음과 같이 말한다면 이 역시 프로세스간 통신의 규칙이 된다. 내게 빵이 하나 생기면 변수 bread의 값을 1로 변경하겠다. 그리고 그 빵을 먹어버리면 변수 breadᅟ의 값을 0으로 다시 변경하겠다. 그러니 너는 변수 bread의 값을 통해서 내 상태를 파악해라. 즉 프로세스 A는 변수 bread를 통해서 자신의 상태를 프로세스 B에게 말한 셈이고 프로세스 B는 변수 bread를 통해서 프로세스A가 한말을 들은 셈이다. 때문에 두 프로세스가 동시에 접근 가능한 메모리 공간만 있다..
에코 클라이언트의 입출 루틴 분할 입출력 루틴의 분할이 의미하는 바를 이해했으니 실제 코드상에서 입출력 루틴을 분할해보자 분할의 대상은 에코클라이언트이다. 다음 에코 클라이언트는 앞서 소개한 에코 서버인 예제 echo_mpserv.c와 함께 동작시키면된다 . echo_mpclient.c 예제 #include #include #include #include #include #include #define BUF_SIZE 30 void error_handling(const char *message); void read_routine(int sock, char *buf); void write_routine(int sock, char *buf); int main(int argc, char *argv[]) { in..
10-05 TCP의 입출력 루틴(Routine)분할 입출력 루틴 분할의 의미와 이점 지금까지 구현한 에코 클라이언트의 데이터 에코방식은 다음과같다 서버로 데이터를 전송한다. 그리고는 데이터가 에코되어 돌아올때까지 기다린다 무조건 기다린다 그리고 에코되어 돌아온 데이를 수신하고 나서야 비로소 데이터를 추가로 전송할 수 있다. 즉 한번 데이터를 전송하면 에코 되어 돌아오는 데이터를 수신할 때까지 마냥 기다려야 했다 기다림의 이유 : 프로그램 코드의 흐름이 read와 write를 반복하는 구조였기때문이다. 코드흐름의 분리를 못한 이유는 하나의 프로세스를 기반으로 프로그램이 동작했기 때문이다. 그러나 이제는 둘 이상의 프로세스를 생성할수 있으니 이를 바탕으로 데이터의 신과 수신을 분리해보자 분리를 위한모델은 다..
다중 접속 에코 서버의 구현 멀티 프로세스기반의 다중접속 에코서버 예제 이다 Chapter04의 에코 클라이언트와 함께 실행하자 echo_mpserv.c 예제 #include #include #include #include #include #include #include #include #define BUF_SIZE 30 void error_handling(const char* message); void read_childproc(int sig); int main(int argc, char *argv[]) { int serv_sock, clnt_sock; struct sockaddr_in serv_adr, clnt_adr; pid_t pid; struct sigaction act; socklen_t ad..
시그널핸들링을 통한 좀비 프로세스의 소멸 remove_zombie.c #include #include #include #include #include void read_childproc(int sig) { int status; pid_t id = waitpid(-1, &status, WNOHANG); if(WIFEXITED(status)) { printf("Removed proc id: %d \n", id); printf("Child send: %d \n", WEXITSTATUS(status)); } } int main(int argc, char *argv[]) { pid_t pid; // 시그널 SOGCHLD에 대한 시그널 핸들러의 등록과정을 보이고 있다 // 이로써 자식 프로세스가 종료되면 7행에 정..
alarm함수 #include unsigned int alarm(unsigned int seconds); -> 0 또는 SIGALRM 시그널이 발생하기까지 남아있는 시간을 초 단위로 반환 위 함수를 호출하면서 양의 정수를 인자로 전달하면 전달된 수에 해당하는 시간(초단위)이 지나고 SIGALRM시그널이 발생한다 그리고 0을 인자로 전달하면 이전에 설정된 SIGALRM시그널 발생의 예약이 취소된다. 그런데 위의 함수호출을 통해서 시그널의 발생을 예약만 해놓고, 이 시그널이 발생했을 때 호출되어야 할 함수를 지정하지 않으면(signal함수호출을 통해서) 프로세스가 그냥 종료되어 버리니 이를 주의해야 한다. signal.c 예제 #include #include #include // 시그널이 발생했을 때 호출되..
좀비 프로세스의 소멸2: waitpid함수의 사용 wait함수의 블로킹이 문제가 된다면 waitpid함수의 호출을 고려하면된다. 이는 좀비 프로세스의 생성을 막는 두 번째 방법이자 블로킹 문제의 해결책이기도하다 #include pid_t waitpid(pid_t pid, int * statloc, int options); -> 성공시 종료된 자식 프로세스의 ID(또는 0) 실패시 -1 반환 pid : 종료를 확인하고자 하는 자식 프로세스의 ID 전달, 이를 대신해서 -1을 전달하면 wait함수와 만찬가지로 임의의 자식 프로세스가 종료되기를 기다린다. statloc : wait 함수의 매개변수 statloc과 동일한 의미로 사용된다. options 헤더파일 sys/wait.h에 선언된 상수 WNOHANG을..
Chapter 10 멀티프로세스 기반의 서버구현 10-1 프로세스의 이해와 활용 두가지 유형의 서버 첫번째 연결요청자 접속대기시간은 0초 50번째 연결요청자의 접속대기시간은 50초 100번째 연결요청자의 접속대기시간은 100초 그러나 연결만되면 1초안에 서비스를 완료해주는 서버 모든 연결요청자의 접속대기시간은 1초를 넘기지 않습니다. 그러나 서비스를 제공받는데 걸리는 시간은 평균적으로 2~3초인 서버 어떠한 서버가 좋을지 고민할 필요가 없다 만약 당신이 100번째 연결요청자라면 100초를 기다리는것보다 1초를 기다려서 2~3초에 서비스를 제공받는게 훨씬 좋은게 당연하다 . 다중접속 서버의 구현 방법들 전체적인 서비스 제공시간이 조금 늦어지더라도 연결요청을 해오는 모든 클라이언트에게 동시에 서비스를 제공해..
주소의 재할당 Time-Wait 상태의 단점 : 시스템에 문제가 생겨서 서버가 갑작스럽게 종료된 상황에서 재빨리 서버를 재 가동시켜서 서비스를 이어가야해도 Time-wait상태라면 바로 접속이 불가능해진다. 따라서 항상 Time-wait상태가 반가운것은 아니다. 또한 Time-wait상태는 상황에 따라서 더 길어질 수 있어서 더큰 문제가 될 수도 있다. 아래 과정은 종료과정인 Four-way handshaking 과정에서 Time-wait 상태가 길어질 수 밖에 없는 문제상황이다. 호스트 A가 전송하는 Four-way handshaking 과정에서 마지막 데이터가 손실이 되면 호스트 B는 자신이 보낸 FIN메시지를 호스트 A가 수신하지 못한것으로 생각하고 FIN메시지를 재전송한다 그러면 FIN메시지를 수..
Time - wait 상태 위의 four-way handshaking 과정을 살펴보자 위 그림에서 호스트 A를 서버라고 보면, 호스트 A가 호스트B로 FIN메시지를 먼저 보내고 있으니 서버가 콘솔상에서 cTRL+ c를 입력한 상황으로 볼 수 있다. 그런데 여기서 주목할 점은 연결의 해제 과정인 Four-way handshaking 이후에 소켓이 바로 소멸되지 않고 Time-wait 상태라는 것을 일정시간 거친다는 점이다. 물론 Time-wait상태는 먼저 연결의 종료를 요청한 (먼저 FIN메시지를 전송한)호스트만 거친다. 이때문에 서버가 먼저 연결의 종료를 요청해서 종료하고 나면, 바로 이어서 실행을 할 수 없는 것이다. 소켓이 Time-wait상태에 있는 동안에는 해당 소켓의 PORT번호가 사용중인 상..
09-2 : SO_REUSEADDR 주소할당 에러(Binding Error)발생 SO_REUSEADDR 옵션에 대한 이해에 앞서 Time-Wait 상태를 먼저 이해해야한다. 이를 위한 예제 reuseadr_eserver.c 를 보자 #include #include #include #include #include #include #define TRUE 1 #define FALSE 0 void error_handling(const char *message); int main(int argc, char *argv[]) { int serv_sock, clnt_sock; char message[30]; int option, str_len; socklen_t optlen, clnt_adr_sz; struct soc..
getsockopt 함수의 호출방법 예제 : 프로토콜 레벨이 SOL_SOCKET이고 이름이 SO_TYPE인 옵션을 이용해서 소켓의 타입정보( TCP or UDP)를 확인하는 예제이다. #include #include #include #include void error_handling(const char* message); int main(int argc, char * argv[]) { int tcp_sock, udp_sock; int sock_type; socklen_t optlen; int state; optlen = sizeof(sock_type); tcp_sock = socket(PF_INET, SOCK_STREAM, 0); // TCP소켓을 생성한다. udp_sock = socket(PF_INET..
09-1 소켓의 옵션과 입출력 버퍼의 크기 소켓의 다양한 옵션 SQL_SOCKET SO_SNDBUF / get 0 / set 0 SO_RCVBUF / get 0 /set 0 SO_REUSEADDr / get 0 / set 0 SO_KEEPALIVE /get 0 / set 0 SO_BROADCAST / get 0 / set 0 SO_DONTROUTE / get 0 / set 0 SO_OOBINLINE / get 0 / set 0 SO_ERROR / get 0 / set x SO_TYPE / get 0 / set x IPPROTO_IP IP_TOS / get 0 / set 0 IP_TTL / get 0 / set 0 IPMULTICAST_TTL / get 0 / set 0 IP_MULTICAST _LOOP ..
구조체 hostent의 정의부분만 놓고 보면 구조체멤버 h_addr_listㅏ 가리키는 것은 문자열 포인터 배열(둘 이상의 문자열 주소 값으로 구성된 배열)이다. 그러나 문자열 포인터 배열이 실제 가리키는 것은(실제 저장하고 있는 것은)문자열의 주소값이 아닌 in_addr 구조체 변수의 주소 값이다. 위 그림은 구조체 멤버 h_addr_list의 참조관계를 보이고 있다. 때문에 위 예제에서 형변환 및 inet_ntoa함수의 호출을 동반하는 것이다. 왜 in_addr*이 아닌 char*인가? 구조체 hostent의 멤버 h_addr_list가 가리키는 배열이 구조체 in_addr의 포인터 배열이 아닌, char형 포인터 배열인 이유가 궁금할 것이다. 왜냐하면 hostent는 IPv4만을 위해 정의된 구조체..
babystep
'책/윤성우 TCPIP' 카테고리의 글 목록