예제의 프로그램을 실행하면 이상없이 자료 송수신이 잘됩니다. 그런데 문제는 server쪽입니다. 프로그램을 강제 종료하든 그냥 종료하든 다시 실행하면 bind() 에서 에러가 발생합니다.
프로그램에도 이상이 없는데 왜 이럴까? 또, 몇 초 있다가 다시 실행하면 아무 이상없이 실행 됩니다.
이유는 프로그램에서 소켓을 close() 함수를 이용하여 소켓을 소멸 시켜도 커널은 바로 속멸 시키지 않고 몇 초 정도 생명(?)을 유지시켜 줍니다. 이렇게 함으로써 클라이언트와 아직 처리되지 않는 전문을 마저 처리할 수 있도록 하기 위함입니다.
이와 같이 바로 죽이지 않고 대기 시키는 상태를 TIME_WAIT 상태라고 하는데, bind()된 소켓이 아직 죽지도 않았는데 같은 주소, 같은 포트로 또 다른 소켓이 bind() 요청을 해오니 커널에서는 에러를 낼 수 밖에 없습니다.
또한 bind() 에러가 발생한 상태에서 다시 bind() 요청을 하면 이전 소켓의 생명 시간은 다시 초기화가 되기 때문에 계속 bind()함수를 호출해 주면 이전 소켓은 더 오래 살아 남습니다. 어쩔 수 없이 이전 소켓의 TIME-WAIT 상태가 끝날 때까지 기다려야 합니다.
소켓 옵션에 SO_REUSEADDR 적용
프로그램을 작성하면서 매번 디버깅 때 마다 기다리고 있을 수 만은 없죠. 이럴 때 소켓의 옵션, 즉 속성을 바꾸어 줍니다.
int option;
server_socket = socket( PF_INET, SOCK_STREAM, 0);
option = 1; // SO_REUSEADDR 의 옵션 값을 TRUE 로
setsockopt( server_socket, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option) );
이렇게 SO_REUSEADDR을 지정해 주면 같은 포트에 대해 다른 소켓이 bind()되는 것을 허락해 주기 때문에 bind()에러 없이 프로그램을 실행할 수 있습니다.
출처 : http://forum.falinux.com/zbxe/?document_srl=406056
'학습자료(~2017) > 리눅스' 카테고리의 다른 글
printk 커널 함수 출력 결과 확인방법 (0) | 2011.04.07 |
---|---|
리눅스 커널에 시스템 콜 추가하는 간략한 설명 (0) | 2011.04.06 |
리눅스 2.6.35에 시스템콜 추가 방법 (2) | 2011.04.06 |
리눅스 - 압축, 압축해제(압축풀기) (0) | 2011.04.01 |
우분투에서 ncurses (0) | 2011.04.01 |