UDP의 데이터 송수신 특성과 UDP에서의 connect 함수 호출
- UDP의 데이터 송수신 특성: 송수신하는 데이터에 경계가 존재
- TCP의 경우 데이터 송수신 과정에서 호출하는 입출력 합수의 호출 횟수는 큰 의미를 지니지 않지만 UDP의 경우 입출력 함수의 호출 횟수가 큰 의미를 지님
- 입력 함수의 호출 횟수와 출력 함수의 호출 횟수가 일치해야 송신된 데이터의 전부를 읽을 수 있다.
// host1
#define BUF_SZ 30
int main(int argc, char* argv[])
{
SOCKET sock;
SOCKADDR_IN serv_adr, clnt_adr;
int clnt_sz, str_len;
WSADATA wsaData;
char message[BUF_SZ];
if (argc != 2)
{
printf("usage: %s <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
err_handling("startup() error");
sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
err_handling("socket() error");
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = htonl(ADDR_ANY);
serv_adr.sin_port = htons(atoi(argv[1]));
if (bind(sock, &serv_adr, sizeof(serv_adr)) == SOCKET_ERROR)
err_handling("bind() error");
for (int i = 0; i < 3; i++)
{
Sleep(5000); // 5sec 간격
clnt_sz = sizeof(clnt_adr);
str_len = recvfrom(sock, message, BUF_SZ, 0, &clnt_adr, &clnt_sz);
message[str_len] = 0;
printf("msg %d: %s\n", i + 1, message);
}
closesocket(sock);
WSACleanup();
return 0;
}
// host2
#define BUF_SZ 30
int main(int argc, char* argv[])
{
SOCKET sock;
int adr_sz;
SOCKADDR_IN serv_adr;
WSADATA wsaData;
char* msg[3] = {
"Hi~",
"I'm another UDP host",
"nice to meet you"
};
if (argc != 3)
{
printf("usage: %s <ip> <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
err_handling("startup() error");
sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
err_handling("socket() eror");
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
serv_adr.sin_port = htons(atoi(argv[2]));
for (int i = 0; i < 3; i++)
{
sendto(sock, msg[i], strlen(msg[i]), 0, &serv_adr, sizeof(serv_adr));
}
closesocket(sock);
WSACleanup();
return 0;
}
- host1에서 recvfrom함수를 호출하기 이전에 5초의 지연시간이 있기 때문에 데이터는 이미 host1에 전송된 상태지만 UDP는 첫번째 recvfrom 함수의 호출을 통해 host2의 첫번째 sendto 함수에서 송신된 데이터만을 출력
// 출력
msg 1: Hi~
msg 2: I'm another UDP host
msg 3: nice to meet you
- UDP 데이터그램: UDP socket이 전송하는 패킷
- TCP 패킷과 다르게 UDP 데이터그램은 데이터의 일부가 아닌 그 자체가 하나의 데이터 (하나의 패킷 == 하나의 데이터)
- connected UDP socket, unconnected UDP socket
- TCP socket: 데이터 전송 목적지의 IP, PORT번호 할당
- UDP socket:데이터 전송 목적지의 IP, PORT번호 할당하지 않음
: unconnected UDP socket에서 sendto 함수를 통한 데이터의 전송과정
1. UDP socket에 목적지의 IP, PORT 번호 할당
2. 데이터 전송
3. UDP socket에 할당된 목적지의 주소정보 삭제
: connected UDP socket에서 sendto 함수를 통한 데이터의 전송과정
1. 데이터 전송 (송수신의 대상이 정해졌으므로 write, read함수 호출 가능)
- unconnected UDP socket: 목적지의 주소정보가 할당되어 있지 않은 socket
- connected UDP socket: 목적지의 주소정보가 할당되어 있는 socket
: 기본적으로 UDP socket은 unconnected socket이지만 하나의 호스트와 오랜 시간 데이터를 송수신해야 한다면 connected UDP socket이 효율적
- connected UDP socket 생성
- UDP socket을 대상으로 connect함수 호출: 목적지의 UDP socket과 연결설정 과정을 거치지 않고 목적지의 IP, PORT번호 할당
// connected UDP socket _host1
// connected udp socket
#define BUF_SZ 30
int main(int argc, char* argv[])
{
SOCKET sock;
int adr_sz;
SOCKADDR_IN serv_adr;
WSADATA wsaData;
char* msg[3] = {
"Hi~",
"I'm another UDP host",
"nice to meet you"
};
if (argc != 3)
{
printf("usage: %s <ip> <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
err_handling("startup() error");
sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
err_handling("socket() eror");
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
serv_adr.sin_port = htons(atoi(argv[2]));
if (connect(sock, &serv_adr, sizeof(serv_adr)) == SOCKET_ERROR)
err_handling("connecnt() error");
for (int i = 0; i < 3; i++)
{
send(sock, msg[i], strlen(msg[i]), 0);
}
closesocket(sock);
WSACleanup();
return 0;
}