프로그래밍의 기초/TCP | IP

UDP의 데이터 송수신 특성과 UDP에서의 connect 함수 호출

Kim나현 2022. 1. 12. 15:43
반응형
  • 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;
}
반응형