윤성우의 열혈 TCP/IP 소켓 프로그래밍을 보며 내용과 생각을 정리하는 글입니다.
지난 글에서 네트워크 프로그래밍 이란 소켓을 통해 데이터를 송수신 하는 프로그램을 작성하는 것 이라고 하였다.
이어서 데이터 송수신 방법에 따라 TCP/UDP 로 소켓 종류를 나누었는데, 이번 글에서 알아볼 것은 UDP 이다.
UDP 는 User Datagram Protocol
의 약자로 데이터를 Datagram 이라는 메세지 단위로 전송이 되며, 그 크기는 65535 바이트이다.
TCP 와는 다르게 데이터의 경계가 정해져 있고, 그 범위를 넘으면 데이터가 나눠서 보낸진다.
여기서 다시 나오는 이야기가 데이터의 경계인데 일전에 이야기 했듯이 TCP 와 UDP 의 데이터 경계의 의미는 한번에 보내진 데이터(패킷 모음)을 여러번에 걸쳐서 받을 수 있냐는 것이다.
왜 TCP 가 데이터의 경계를 가지지 않는가에 대해서는 이 글을 쓰면서 생각하건데, TCP 방식에서는 1:1 통신 구조, 즉 통신 대상이 명확하기 때문에 상대방이 보낸 데이터를 어떻게 읽던지 크게 제한을 둘 필요가 없어 보인다. 또 어차피 손실된 데이터 없이 받을 수 있기 때문에 더더욱이 문제가 되지 않는다.
반대로 UDP 는 송신자가 다수일 수도 있고, 수신자 입장에서는 날아온 데이터가 누가 몇개를 보냈는지 알 수 있는 방법이 없기 때문에 하나의 데이터그램 단위로 수신하게 된다.
UDP 는 비연결형 통신
을 지향하는데, 비연결형이란 송신자와 수신자간의 연결이 따로 존재하지 않는다는 것이다.
연결이 존재하지 않는다는 것은 수신측에서 송신자가 누군지 모른다는 것을 의미하고 그렇기 때문에 전송과정에서 데이터가 유실되었는지 여부를 확인할 수 없다.
TCP 통신에서는 송신자가 "0번 부터 상자 10개 보냈어~" 라고 한다면 수신측에서 0번부터 9번까지 상자가 잘 도착했는지 확인하고 누락된게 있으면 "0번 부터 상자 10개 다시 보내줘~" 의 방식으로 패킷의 안정적인 전송을 보장했는데
UDP 수신자가 "어 패킷 왔네" 하고 데이터를 받으면 그냥 끝이다 송신자가 누군지 보낸 데이터가 이거 하나 뿐인지는 궁금해하지 않는다
송신지가 어딘지 알 순 있다
udp 소켓 생성
#include <sys/socket.h>
#include <arpa/inet.h>
socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)
bind : TCP 와 동일하지만, 클라이언트는 따로 bind 과정을 거치지 않는다
sendto 호출 시 자동으로 IP 와 port 가 할당되기 때문
데이터 전송
ssize_t sendto(int sock, void *buff, size_t nbytes,
int flags, struct sockaddr *to, socklen_t addrlen);
TCP 와 다른 점은 TCP 는 connect 로 한번 연결해놓으면 socket 을 통해 데이터가 전송가능한 반면 UDP 는 coonection 의 개념이 없기 때문에 매 데이터 전송 시 마다 이렇게 목적지 정보를 명시해야한다.
sock : 데이터를 보낼 소켓
buff / nbytes : 데이터를 얼마만큼 보낼지
flags : 전송 옵션 지정
to : 전송지 정보
addrlen : 전송지 정보 크기
데이터 수신
recvfrom(int fd, void *buff, size_t, nbytes, int flags,
struct sockaddr *from, socklen_t *addrlen)
UDP 통신은 1:N 즉 전송지가 여러곳이 될 수 있다. 따라서 전송지의 정보를 식별할 수 있는 방법을 제공한다.
하지만 여전히 전송자가 총 몇개의 데이터를 보냈는지에 대한 정보는 존재하지 않는다.
* connect 를 사용하여 connected UDP 를 구현할 수 있지만 실질적으로 연결된 것은 아니고 서버 주소 정보만을 저장한다는 의미를 가진다