• Server
    - 1_server
     : 기본 서버 구조

    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
    #include <stdio.h>
     
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
     
    #include <arpa/inet.h>
    #include <netinet/in.h>
     
    int main()
    {
        // 1. socket 생성    
        int sock = socket(PF_INET, SOCK_STREAM, 0);
     
        // 2. bind() : 소켓 주소 지정
        struct sockaddr_in saddr = {0, };
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(4000);
     
        // 연결을 받을 주소
        saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        bind(sock, (struct sockaddr*)&saddr, sizeof saddr);
     
        // 3. 연결 대기 상태로 만든다. : listen
        listen(sock, 5);
     
     
        // 4. 클라이언트 요청 수락 : accept
        struct sockaddr_in caddr = {0, };
        socklen_t clen = sizeof(caddr);
        int csock = accept(sock, (struct sockaddr*)&caddr, &clen);
     
         
        printf("연결이 수립되었습니다.\n");
     
        close(csock);
        close(sock);
    }


    - 2_server
     : 여러 클라이언트 받아들이기

    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
    #include <stdio.h>
     
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
     
    #include <arpa/inet.h>
    #include <netinet/in.h>
     
    int main()
    {
        int sock = socket(PF_INET, SOCK_STREAM, 0);
     
        struct sockaddr_in saddr = {0, };
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(4000);
        // saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        // 문제점 : 127.0.0.1로 오는 연결만 받을 수 있다.
     
        // 해결방법 : INADDR_ANY(0.0.0.0);
        saddr.sin_addr.s_addr = INADDR_ANY; // 0.0.0.0
     
        bind(sock, (struct sockaddr*)&saddr, sizeof saddr);
        listen(sock, 5);
     
        while (1)
        {
            struct sockaddr_in caddr = {0, };
            socklen_t clen = sizeof(caddr);
            int csock = accept(sock, (struct sockaddr*)&caddr, &clen);
     
            char* cip = inet_ntoa(caddr.sin_addr);
     
            printf("Connected from %s\n", cip);
            close(csock);
        }
     
        close(sock);
    }

  • - 3_server
     : bind(): Address already in use 해결
    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
    #include <stdio.h>
     
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
     
    #include <arpa/inet.h>
    #include <netinet/in.h>
     
    // 1. bind() : Adress already in use
    //  먼저 연결을 종료한 측의 소켓은 유지되어야 한다. - TIME_WAIT
    //  => TIME_WAIT 상태가 종료 되기 이전에 해당 포트로 서버를 바인드
    //     하는 것이 불가능하다.
     
    // 2. TIME_WAIT : 같은 포트의 연결을 손상 시킬 수 있다.
    // 3. 클라이언트 포트는 동일한 포트로 바인딩 되지 않는다.
    // 4. 최신 네트워크 커널의 구현은 SYN의 시퀀스 번호가 TIME-WAIT 상태의
    //    연결로부터 마지막 시퀀스 번호보다 클 경우에만 연결을 허용한다.
    // 5. TIME_WAIT은 먼저 연결을 종료한 쪽에서 발생한다.
    //    클라이언트는 포트가 변경되기 때문에 문제가 없다.
     
    int main()
    {
        int sock = socket(PF_INET, SOCK_STREAM, 0);
     
        struct sockaddr_in saddr = {0, };
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(4000);
        saddr.sin_addr.s_addr = INADDR_ANY; // 0.0.0.0
     
        //----------------
        // 6. 해결방법
        // 서버는 약속된 포트로부터 연결을 받아야 하므로
        // 반드시 주소를 재할당 할 수 있도록 변경해주어야 한다.
        int option = true;
        socklen_t optlen = sizeof(option);
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option, optlen);
        //-----------------
     
        int ret = bind(sock, (struct sockaddr*)&saddr, sizeof saddr);
        if (ret == -1) {
            perror("bind()");
            return -1;
        }
     
     
     
        listen(sock, 5);
     
        struct sockaddr_in caddr = {0, };
        socklen_t clen = sizeof(caddr);
        int csock = accept(sock, (struct sockaddr*)&caddr, &clen);
     
        close(csock);
        close(sock);
    }

  • Client
    - 1_client ~ 2_client
     : 기본 클라이언트 구조

    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
    #include <stdio.h>
     
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
     
    #include <errno.h>
    #include <string.h>
     
    int main()
    {
        int sd = socket(PF_INET,
                SOCK_STREAM, 
                IPPROTO_TCP);
     
        struct sockaddr_in addr = {0, };
        addr.sin_family = AF_INET;
        addr.sin_port = htons(4000);
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
     
        int ret = connect(sd, (struct sockaddr*)&addr, sizeof(addr));
        if (ret == -1) {
            perror("connect()");
            return -1;
        }
     
        printf("Connection succeed!!\n");
        close(sd);
    }


    - 3_client
     : TIME_WAIT 문제 확인

    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
    #include <stdio.h>
     
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
     
    #include <errno.h>
    #include <string.h>
     
    int main()
    {
        int sd = socket(PF_INET,
                SOCK_STREAM, 
                IPPROTO_TCP);
     
        struct sockaddr_in addr = {0, };
        addr.sin_family = AF_INET;
        addr.sin_port = htons(4000);
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
     
        int ret = connect(sd, (struct sockaddr*)&addr, sizeof(addr));
        if (ret == -1) {
            perror("connect()");
            return -1;
        }
     
        printf("Connection succeed!!\n");
     
        sleep(5);
        close(sd);
    }


+ Recent posts