책/윤성우 TCPIP

09-2 : SO_REUSEADDR

babystep 2020. 12. 12. 23:58
728x90

 

  • 09-2 : SO_REUSEADDR
    • 주소할당 에러(Binding Error)발생
      • SO_REUSEADDR 옵션에 대한 이해에 앞서 Time-Wait 상태를 먼저 이해해야한다.
      • 이를 위한 예제 reuseadr_eserver.c 보자

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>

 

#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 sockaddr_in serv_adr, clnt_adr;

    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");

 

    /*

    optlen = sizeof(option);

    option = TRUE;

    setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&option, oplen);

    */

 

    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]));

 

    if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)))

        error_handling("bind() error");

 

    if(listen(serv_sock, 5) == -1)

        error_handling("listen() error");

 

    clnt_adr_sz = sizeof(clnt_adr);

    clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);

 

    while((str_len = read(clnt_sock, message, sizeof(message))) != 0)

    {

        write(clnt_sock, message, str_len);

        write(1, message, str_len);

    }

 

    close(clnt_sock);

    close(serv_sock);

 

 

 

    return 0;

}

 

void error_handling(const char* message)

{

    fputs(message, stderr);

    fputc('\n', stderr);

    exit(1);

}

  • 예제는 지금까지 차례 구현해 에코 서버 프로그램이다 따라서 Chapter04에서 소개한 에코 클라이언트와 함께 실행하면 된다.
  • 클라이언트 콘솔에서 q메세지를 입력하거나 CTRL+C 입력해서 프로그램을 종료시켜보면 Four-way handshaking 과정을 거치며 서버측으로 FIN메세지가 전달된다. 프로그램을 강제종료할 경우에도 운영체제가 파일 소켓을 모두 닫아주는데 이과정에서 close함수를 호출한 것과 마찬가지로 서버측으로 FIN메세지가 전달된다.
  • 상황은 별다른 현상은 관찰되지 않는것으로 느껴질수있다 그렇다 클라이언트가 먼저 연결종료를 요청하는 경우는 매우 일반 적인 상황이기 때문에 별다른 일이 발생할것이없다. 서버의 재실행도 문제되지 않는다
  • 그러나 서버와 클라이언트가 연결된 상태에서  서버측 콘솔에서 CTRL+C 입력해서 서버 프로그램을 강제종료한다면 서버가클라이언트측으로 먼저 FIN메세지를 전달하는 상황이 된다.
  • 위의 상황이 되면 동일한 PORT번호를 기준으로 서버를 재실행하면 bind()error라는 메시지가 출력될 서버는 실행되지 않고 3분정도가 지나서야 재실행시 정상적인 실행이된다 두방식의 유일한 차이점은 FIN메세지를 누가먼저 전송했는지에 있다.
728x90