C 언어에서 UDP 서버는 데이터를 받은 뒤 누가 보냈는지도 알아야 답장을 보낼 수 있다.
이때 recvfrom()을 사용하면 데이터와 송신자 주소를 한 번에 얻을 수 있다.
형태는 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) 이다.
addrlen에는 호출 전에 주소 버퍼의 크기를 넣고 호출 후에는 실제 주소 길이가 기록된다.
UDP는 데이터그램 단위가 유지되므로 한 번 호출할 때 데이터그램 하나를 꺼낸다.
fd는 미리 만든 UDP 소켓이다. 데이터에는 문자열뿐 아니라 바이너리도 올 수 있으므로 받은 버퍼를 무조건 %s로 출력하지 않고 반환 길이로 처리한다.
char buf[1500];
struct sockaddr_storage peer;
socklen_t peer_len = sizeof(peer);
ssize_t n = recvfrom(fd, buf, sizeof(buf), 0,
(struct sockaddr *)&peer, &peer_len);
if (n < 0) {
perror("recvfrom");
} else {
printf("UDP 데이터 %zd바이트 수신\n", n);
}
받을 버퍼보다 데이터그램이 크면 기본 동작에서는 뒷부분이 잘리고 그 데이터그램의 나머지는 다시 받을 수 없다.
리눅스에서는 MSG_TRUNC를 이용해 원래 데이터그램 길이를 확인할 수 있다.
src_addr와 addrlen을 NULL로 주면 송신자 주소가 필요 없는 recv()처럼 사용할 수도 있다.
답글 달기