6.UDP 기반 서버/클라이언트

#.udp 소켓 특징

 

 1.장점

 - tcp 보다 간결한 구조로 설계되어서 상황에 따라 좋은 성능을 발휘 한다.(seq와 같이 패킷에 번호부여하는일 없음)

 - 프로그램 관점에서 구현이 용이하다.

 - 데이터 손실이 자주 발생하지는 않는다.

 - 신뢰성 보다 성능이 중시되는 상황에서 좋은 선택이 될 수 있다.

 

2.단점

 - 상대방의 수신여부를 알 수 없다.

 - 전송도중에 데이터가 분실될 수 있다.

 - 신뢰할 수 없는 전송방법을 제공한다.

 - 데이터를 전송할 때마다 반드시 목적지의 주소 정보를 별도로 추가해야한다.

  (tcp 처럼 연결된 상태가 아니기 때문에.)

 

 tcp는 신뢰성 없는 ip를 기반으로 신뢰성 있는 데이터 송수신을 위해서 흐름제어를 하지만,

 udp는 흐름제어가 존재하지 않는다. 흐름제어 존재 유무가 tcp와 udp의 큰 차이점이다!

 

 

 #.데이터 송수신 속도

 - 일반적으로 udp가 더 빠르다.

 - 송수신하는 데이터의 성격에 따라 tcp는 udp와 비슷한 속도를 내기도 한다.

 - 한번에 송수신 하는 데이터의 양이 크면 클수록 tcp는 udp 못지 않은 속도를 낸다.

 

udp 내부 동작 원리

 #.udp 내부 동작 원리

 - udp의 역할 중 가장 중요한 역할은, 호스트로 수신된 udp 패킷을 port정보를 참조하여

 최종목적지인 udp 소켓에 전달하는것.

 

 #.udp 사용 예

 - 압축파일의 경우 tcp 기반으로 송수신이 이루어지나, 실시간 멀티미디어(영상, 음성)의 경우

 속도가 중요하므로 udp 기반의 구현을 고려할만하다.

 

tcp와 udp 차이점

 

 #.tcp가 udp 보다 느린 이유

 - 데이터 송수신 이전, 이후에 연결 설정 및 해제 과정이 존재한다.

 - 데이터 송수신 과정에서 거치는 신뢰성 보장을 위한 흐름제어가 존재한다.

 - 송수신하는 데이터의 양이 작으면서, 여러번 연결이 필요한 경우에는 udp가 훨씬 효율적이고 빠르다.

 

 #.udp 소켓 생성과 데이터 송수신 과정만 필요

 udp 서버/클라이언트는 tcp 처럼 연결된 상태로 데이터 송수신을 하는 것이 아니기 때문에,

 연결 설정, 해제 과정이 필요없다. (listen, accept 함수 호출이 불필요하다.)

 즉, udp 소켓 생성과 데이터 송수신 과정만 필요하다.

 

 #.소켓의 개수

 tcp에서는 소켓과 소켓의 관계가 일대일로 대응되어 연결된다.

 서버가 <10개의 클라이언트>에 서비스를 제공하려면 서버에 <서버소켓 1개>와 <클라이언트와의 연결을 위한

 10개의 추가소켓>이 필요하다. 그러나 udp에서는 서버와 클라이언트 모두 하나의 소켓만 있으면 된다.

 

 #.우체통 비유

 - 데이터 수신지의 주소만 있으면 udp소켓을 이용해서 어디든 데이터를 보낼 수 있다. 우체통(udp소켓)에 편지를 넣으면

 수신지로 가는것 처럼)

 

#.sentto() 함수는 UDP/IP 통신에서 소켓으로 데이터를 전송한다.

UDP/IP 통신에서는 TCP/IP와는 달리 read()와 write()를 사용하지 않고 recvform()과 sendto()함수를 이용하여 자료를 송수신합니다. sendto()함수를 대신 사용하는 이유는 전송할 목적지를 지정할 수 있기 때문이며, recvform()함수를 사용하는 이유는 수신되는 자료 외에도 송신지의 정보를 함께 얻을 수 있기 때문입니다. 그러므로 TCP/IP처럼 한번 연결되면 연결된 시스템과 자료를 주고 받지만 UDP/IP는 자유롭게 시스템 주소를 바꾸어 가면서 자료를 송수신 할 수 있습니다.

 

- 형태   

int sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);

 

- 인수

int s    : 소켓 디스크립터

void *msg    : 전송할 데이터

size_t len    : 데이터의 바이트 단위 길이

int flags    : 전송을 위한 옵션으로 아래의 값을 사용할 수 있습니다.

sockaddr *to    : 목적지 주소 정보

socklen_t tolen    : 목적지 주소 정보의 크기

 

-flags    옵션 설명

MSG_OOB    SOCK_STREAM에만 사용되며 out-of-band 데이터로 전송될 수 있음을 나타냅니다.

MSG_DONTROUTE    데이터는 라우팅될 수 없음으로 지정합니다.

MSG_DONTWAIT    NONE BLOCKING 통신이 가능하도록 합니다.

MSG_NOSIGNAL    상대방과 연결이 끊겼을 때, SIGPIPE 시그널을 받지 않도록 합니다.

 

- 반환

-1 이외  : 실제 전송한 바이트 수

-1      : 실패

 

 

#.recvfrom() 함수는 UDP/IP 통신에서 소켓으로부터 데이터를 수신합니다.

 

- 형태   

int recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);

 

- 인수

int s    : 소켓 디스크립터

void *buf    : 자료 수신을 위한 버퍼 포인터

size_t len    : 버퍼의 바이트 단위 길이

int flags    : 수신을 위한 옵션으로 아래의 값을 사용할 수 있습니다.

 

- flags    옵션 설명

MSG_OOB    SOCK_STREAM에만 사용되며 out-of-band 데이터로 전송될 수 있음을 나타냅니다.

MSG_DONTROUTE

데이터는 라우팅될 수 없음으로 지정합니다.

MSG_DONTWAIT    NONE BLOCKING 통신이 가능하도록 합니다.

MSG_NOSIGNAL    상대방과 연결이 끊겼을 때, SIGPIPE 시그널을 받지 않도록 합니다.

 

sockaddr *to    : 전송한 곳의 주소 정보

socklen_t tolen    : 주조 정보의 크기

 

- 반환

-1 이외 : 실제 수신한 바이트 수

-1     : 실패

 

 

#.서버예제

 

#.클라이언트 예제

 

 "udp 소켓은 tcp 소켓과 달리 연결 설정이 필요 없기 때문에 listen(), accept() 함수를 호출 하지 않는다."

 

 #.클라이언트 소켓 주소 할당 시점은?

 - tcp 클라이언트 소켓의 주소는 connect 함수가 호출될때 ip 와 port(랜덤) 번호가 자동으로 할당된다.

 - udp에서는 sendto 함수 호출 이전에 해당 소켓(데이터 발신지)의 주소 정보가 할당되어 있어야 한다.

 

 1.sendto 함수 호출 이전에 bind 함수 호출 하여 명시적으로 주소 정보 할당.

 2.sendto 함수가 처음 호출되는 시점에 해당 소켓(발신지)에 ip와 port 번호가 자동으로 할당됨

 (2번이 일반적인 구현방법이다. ip는 호스트 ip, port 번호는 현재 사용하지 않고 있는 번호 하나를 임의로 할당,

 프로그램 종료까지 주소 정보는 유지)

 

 

 #.udp 소켓은 데이터의 경계가 존재한다.

 - 데이터 송수신과정에서 호출하는 입출력 함수의 호출횟수가 의미를 가진다.

 - 입력함수의 호출횟수와 출력함수의 호출횟수가 완벽히 일치해야 송신된 데이터 전부를 수신할 수 있다.

 

 

예제 1 (5초 간격으로 총 3회의 데이터를 받는 함수를 호출하고 예제 2로 부터 데이터를 받는다.)

 

예제2 (총 3회의 sendto 함수를 호출하여 예제 1로 데이터를 3번 전송한다.)

결과

 

예제2는 총 3회의 sendto 함수를 호출해서 데이터를 예제1로 전송했고, 예제 1은 총 3회의 recvfrom 함수를 통해서 데이터를 수신한다. 그런데 recvfrom 함수 호출에는 5초간 지연시간이 존재함으로, recvfrom 함수가 호출되기 전에 3회의 sendto 함수 호출이 진행되어 이미 데이터는 예제 1에 전송된 상태다. tcp라면 단 한번의 입력함수를 호출해서 모든 데이터를 읽을 수 있지만, udp는 이 상황에서도 3회의 recvfrom 함수호출이 요구된다. 이로써 udp 기반의 데이터 송수신 과정에서는 입출력 함수의 호출횟수를 일치시켜야 한다!

 

 #.udp 데이터 그램

 - udp 소켓이 전송하는 패킷을 가리킨다.

 - 데이터 그램도 패킷의 일종인데, tcp 패킷과 달리 데이터의 일부가 아니라,

   그 자체가 하나의 데이터로 의미를 가질때 이처럼 표현을 한다.

 (udp는 데이터의 경계가 존재하기 때문에 하나의 패킷 = 하나의 데이터로 간주된다.

 그래서 데이터 그램이라고 표현한다.)

 

 #.connceted UDP 소켓, unconnected UDP 소켓

 tcp 소켓에는 데이터를 전송할 목적지(수신지)의 ip와 port번호를 등록하는 반면,

 udp 소켓에는 데이터를 전송할 목적지를 등록하지 않고 sendto함수를 호출할때마다

 1.udp소켓에 목적지의 ip와 port를 등록한다.

 2.해당 목적지로 데이터를 전송한다.

 3.udp 소켓에 등록된 목적지 정보를 삭제한다.

 

즉, sendto 함수가 호출될때 마다 위의 과정을 반복한다. 이렇듯 목적지의 주소정보가 계속해서 변경되기 때문에 하나의 UDP 소켓을 이용해서 다양한 목적지로 데이터 전송이 가능한 것이다.

 

 

만약 ip 100.123.122.22, port 90 으로 준비된 총 세개의 데이터를 세번 sendto 함수를 호출해서 전송해야 된다면?

 

위에서 정리한 데이터 전송 세 단계를 총 세번 반복해야 한다. 그래서 하나의 호스트와 오랜 시간 데이터를 송수신 해야한다면, UDP 소켓을 connceted 소켓으로 만드는 것이 효율적이다.

 

#.connceted UDP 소켓 예제

 

 

 

 

 

[출처] : 윤성우 저, "열혈강의 TCP/IP 소켓 프로그래밍", 오렌지미디어