블로그 이미지
하루, 글. 그림. 영상매체. 표현을 도와주는 기기들. 도전 중. 동화다아아
    동화다아아

    카테고리

    분류 전체보기 (176)
    잡담 (1)
    IT 기기-리뷰&뉴스 (7)
    리뷰 - 도서 (1)
    리뷰 - 영상 (0)
    리뷰 - 그림/음악 (1)
    내장형 하드웨어 (163)
    Total
    Today
    Yesterday

    - TCP 프로토콜을 이용산 소켓 프로그래밍

    server

    clinet

    서버에 소켓 생성(client와 연결을 위해 필요한 소켓) - socket()

    서버에 주소 할당 - bind()

    연결 요청 대기모드로 설정 - listen()

    클라이언트 연결 요청시 새로운 소켓 생성 - accept()

    송(write(), send()) / 수신(read(), recv())

    클라이언트 소켓 닫기 - close()

    소켓 생성 - socket()

     

     

     

    연결 요청(접속할 서버의 IP, PORT) - connect()

    송(write(), send()) / 수신(read(), recv())

    소켓 닫기  - close()

            

    ⇒ TCP → 연결형 프로토콜(전화와 비슷)

            → 두 시스템 간 연결이 성공한 후에 데이터 전송 시작함                 

                                                                                 (3-way handshaking)

            → 연결 요청이 왔을 때 위와 같이 3번 이동하며 연결한다.

            

    1) 송신 호스트가 SYN Flag값을 1로 설정한 TCP packet과 임의의 Sequence Number를 수신 호스트로 보낸다.

            Ex)  송신  -------------------------->  수신

                            SYN=1, SEQ=J

    2) 수신 호스트가 Session성립을 원하면 SYN Flag를 1로 설정하고 ACK를 송신 호스트가 보낸 SEQ번호의 다음 번호로 정하고 수신 호스트에 따로 설정한 SEQ번호를 보낸다.

            Ex)  송신  <--------------------------  수신

                            SYN=1, ACK=J+1, SEQ=K

    3) 송신 호스트는 ACK 값을 수신지 호스트가 보낸 SEQ번호의 다음 번호로 정하여 수신 호스트에 보낸다.

            Ex)  송신  -------------------------->  수신

                            ACK=K+1

            → 신뢰성 보장(순차적 데이터 전달, 데이터 재전송)

            → 데이터 경계를 구분하지 않는다.


    ⇒ UDP → 비연결형 프로토콜(편지와 비슷)

            → 연결 없이 통신 가능

            → 비신뢰적인 데이터 전송(전송순서에 상관없이 가장 빠른 전송 지향, 전송도중 데이터가 손실되어도 재전송 되지 않음.)

            → 데이터의 경계를 구분함(Datagram 서비스)



    ⇒ 연결형 서버 → TCP 프로토콜을 이용, TCP 소켓을 사용한다.

       비연결형 서버 → UDP 소켓 사용. (연결 요청을 하지 않는다.)

    ⇒ iterative server → 순서대로 client와 송/수신

                         → client와 서비스 시간이 짧은 경우에 사용한다.

       concurrent server → server와 client 서비스 시간이 불균형 적일 때 사용한다.

    ⇒ client 연결 요청 간 새로운 소켓 생성(accept())부터 client 소켓 닫기(close()) 까지를 반복시키면 iterative server가 된다.



    // helloworld_iterative_server.c에서 연결 요청 수락 부분에 반복문 사용을 통한 iterative server 만들기
         

            // 소켓에 주소 할당

            if( bind(serv_sock, (struct sockaddr*)& serv_addr, sizeof(serv_addr)) == -1)

            {

                    error_handling("bind() error");

            }

            // 연결 요청 대기상태로 진입

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

            {

                    error_handling("listen() error");

            }       

            // 연결 요청 수락

            clnt_addr_size = sizeof(clnt_addr);       

            for(;;) // iterative 서버를 만들기 위해 반복한다.

            {

            clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

            serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

            serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

            // IP주소, INADDR_ANY - 사용중인 ip의 주소를 자동으로 찾아준다.

            // htonl() - little endian 방식을 big endian 방식으로 바꾸어 준다.
         printf("%s\n", inet_ntoa(clnt_addr.sin_addr)); // IP 주소 출력 

            printf("%d\n", ntohs(clnt_addr.sin_port)); // PORT 번호 출력 
         
    if(clnt_sock == -1)

            {

                    error_handling("accept() error");

            }

            // 데이터 전송

            write(clnt_sock, message, sizeof(message));

            sleep(5);

            // 연결 종료

            close(clnt_sock);
         }

            return 0;
    }
    void error_handling(char *message)
    {
            fputs(message, stderr);
            fputc(
    '\n', stderr);
            exit(
    1);
    }  

    ⇒ iterative server 만들기에서 client 소켓 닫기를 하지 않으면 생성된 소켓이 계속 남아있게 된다.

    ⇒ write() / read() 는 send() / recv()로 바꾸어 사용할 수 있다. 단, linux에서만 가능.

    ⇒ send()와 recv()에 대해 살펴보면(man 2 send 명령으로도 찾을 수 있다.)

     → send() 호출의 선언은 아래와 같다.

        int send(int sockfd, const void *msg, int len, int flags);

     → sockfd는 socket()를 통해서 얻었거나 accept()를 통해서 새로 구한, 데이터를 보낼 소켓의 기술자, msg는 보낼 데이터를 가리키는 포인터, len은 보낼 데이터의 바이트 수,  flags는 대부분의 경우 0으로 해야 한다.

     → recv() 호출의 선언은 아래와 같다.

        int recv(int sockfd, void *buf, int len, unsigned int flags);

     → sockfd는 읽어올 소켓의 기술자이며 buf는 정보를 담을 버퍼. len은 버퍼의 최대 크기, flags는 대부분의 경우 0으로 세팅해야 한다.

    ⇒ write(clnt_sock, message, sizeof(message));

     → send(cnt_sock, message, sizeof(message), 0); 으로 바꾸어 쓸 수 있다.



    - udpecho_server/ udpecho_client 테스트

    ⇒ udpecho_client         

     

    ⇒ udpecho_server         

     

            


    Posted by 동화다아아
    , |

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함