Chapter 06. UDP 서버/클라이언트
UDP 서버/클라이언트의 기본 구조와 동작 원리를 이해한다. UDP 애플리케이션 작성에 필요한 소켓 함수를 익힌다. 학습 목표 UDP 서버/클라이언트의 기본 구조와 동작 원리를 이해한다. UDP 애플리케이션 작성에 필요한 소켓 함수를 익힌다. 브로드캐스팅의 개념을 이해하고 UDP를 이용한 구현 방법을 익힌다.
TCP와 UDP (1/3) TCP와 UDP의 공통점 포트 번호를 이용하여 주소를 지정 데이터 오류를 체크함
TCP와 UDP의 차이점 TCP와 UDP (2/3) 항목 TCP UDP ① 연결형(connection-oriented) 프로토콜 - 연결이 성공해야 통신 가능 비연결형(connectionless) 프로토콜 - 연결 없이 통신 가능 ② 데이터 경계를 구분하지 않음 - 바이트 스트림(byte-stream) 서비스 데이터 경계를 구분함 - 데이터그램(datagram) 서비스 ③ 신뢰성 있는 데이터 전송 - 데이터를 재전송함 비신뢰적인 데이터 전송 - 데이터를 재전송하지 않음 ④ 1 대 1 통신(unicast) 1 대 1 통신(unicast), 1 대 다 통신(broadcast), 다 대 다 통신(multicast)
TCP와 UDP (3/3) UDP의 특징 - 연결을 하지 않으므로 connect() 함수를 사용하지 않음. (몇 가지 이유로 인해 connect() 함수를 사용하는 경우도 있음) - 데이터 경계 구분을 위한 작업을 애플리케이션이 하지 않아도 됨 - 프로토콜 수준에서 신뢰성 있는 데이터 전송을 보장하지 않으므로, 필요하다면 애플리케이션 수준에서 신뢰성 있는 데이터 전송 기능을 구현해야 함 - 간단한 소켓 함수 호출 절차만 따르면 다자 간 통신을 쉽게 구현할 수 있음
UDP 서버/클라이언트 동작 원리 (1/2) UDP 서버/클라이언트 동작 원리 UDP 서버 UDP 서버 UDP 클라이언트 #1
UDP 서버/클라이언트 동작 원리 (cont’d) . . . 통신 통신 UDP 클라이언트 #1 UDP 클라이언트 #2 UDP 클라이언트 #1 . . . UDP 클라이언트 #n
예제 동작 방식 UDP 서버/클라이언트 예제 UDP 클라이언트 UDP 서버 fgets() sendto() printf() recvfrom()
UDP/IP 소켓 통신을 위해 필요한 요소 ① 프로토콜 ② 지역(local) IP 주소와 지역 포트 번호 소켓을 생성할 때 결정 ② 지역(local) IP 주소와 지역 포트 번호 서버 또는 클라이언트 자신의 주소 ③ 원격(remote) IP 주소와 원격 포트 번호 서버 또는 클라이언트가 통신하는 상대방의 주소
소켓 데이터 구조체 UDP 서버/클라이언트 분석 (2/4) 서버 클라이언트 애플리케이션 운영체제 네트워크 수신 버퍼 지역 IP 주소 지역 포트 번호 원격 IP 주소 원격 포트 번호 클라이언트 애플리케이션 운영체제 네트워크 • • • 수신 버퍼
UDP 서버/클라이언트 구조 ① UDP 서버/클라이언트 분석 (3/4) socket() bind() recvfrom() sendto() closesocket() UDP 서버 UDP 클라이언트 네트워크
UDP 서버/클라이언트 구조 ② UDP 서버/클라이언트 분석 (4/4) socket() bind() recvfrom() sendto() closesocket() send() recv() UDP 서버 UDP 클라이언트 네트워크 connect()
sendto() 함수 하부 프로토콜(예를 들면, UDP/IP)을 이용하여 애플리케이션 데이터를 전송 데이터 전송 함수 (1/4) sendto() 함수 하부 프로토콜(예를 들면, UDP/IP)을 이용하여 애플리케이션 데이터를 전송 sendto() 함수를 호출할 때, 소켓의 지역 IP 주소와 지역 포트 번호가 아직 결정되지 않은 상태라면 시스템이 자동으로 결정 int sendto ( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen ) ; 성공: 보낸 바이트 수, 실패: SOCKET_ERROR
sendto() 함수 사용 예 데이터 전송 함수 (2/4) // 소켓 주소 구조체를 수신자 주소로 초기화한다. SOCKADDR_IN serveraddr; ... // 보낼 데이터를 저장할 버퍼를 선언한다. char buf[BUFSIZE]; // 보낼 데이터를 버퍼에 저장한다. // 데이터를 보낸다. retval = sendto(sock, buf, strlen(buf), 0, (SOCKADDR *)&serveraddr, sizeof(serveraddr)); if(retval == SOCKET_ERROR) 오류 처리; printf("%d바이트를 보냈습니다.\n", retval);
recvfrom() 함수 수신 버퍼에 도착한 데이터를 애플리케이션 버퍼로 복사 데이터 전송 함수 (3/4) int recvfrom ( SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen ) ; 성공: 받은 바이트 수, 실패: SOCKET_ERROR
recvfrom() 함수 사용 예 데이터 전송 함수 (4/4) // 송신자 주소 저장을 위한 변수를 선언한다. SOCKADDR_IN peeraddr; int addrlen; // 받은 데이터를 저장할 버퍼를 선언한다. char buf[BUFSIZE]; // 데이터를 받는다. addrlen = sizeof(peeraddr); retval = recvfrom(sock, buf, BUFSIZE, 0, (SOCKADDR *)&peeraddr, &addrlen); if(retval == SOCKET_ERROR) 오류 처리; printf("%d바이트를 받았습니다.\n", retval);
브로드캐스팅 (1/6) 통신의 종류 유니캐스팅 브로드캐스팅 멀티캐스팅
브로드캐스팅 (2/6) 브로드캐스팅 원리 송신자
브로드캐스트 데이터를 보내기 위한 절차 ① 소켓에 대해 브로드캐스팅을 활성화시킴 브로드캐스팅 (3/6) BOOL bEnable = TRUE; retval = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&bEnable, sizeof(bEnable)); if(retval == SOCKET_ERROR) err_quit("setsockopt()");
브로드캐스트 데이터를 보내기 위한 절차 (cont’d) 브로드캐스팅 (4/6) 브로드캐스트 데이터를 보내기 위한 절차 (cont’d) ② 브로드캐스트 주소로 데이터를 보냄 // 소켓 주소 구조체를 초기화한다. SOCKADDR_IN remoteaddr; ZeroMemory(&remoteaddr, sizeof(remoteaddr)); remoteaddr.sin_family = AF_INET; remoteaddr.sin_port = htons(9000); remoteaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); // 보낼 데이터를 버퍼에 저장한다. char buf[BUFSIZE]; ... // 데이터를 보낸다. retval = sendto(sock, buf, strlen(buf), 0, (SOCKADDR *)&remoteaddr, sizeof(remoteaddr)); if(retval == SOCKET_ERROR) 오류 처리; printf("%d바이트를 보냈습니다.\n", retval);
브로드캐스트 주소 브로드캐스팅 (5/6) 호스트 ID 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 네트워크 ID 11 . . . . . . . . . . . . 1 네트워크-방향 브로드캐스트 지역 브로드캐스트 11 . . . 1 서브넷-방향 브로드캐스트 서브넷 ID
브로드캐스팅 (6/6) 브로드캐스트 주소 (cont’d) 라우터 네트워크-방향 브로드캐스트 라우터 지역 브로드캐스트