GameChoi 2023. 1. 10. 22:20

1. UDP

1.1 UDP의 의미

 - 데이터를 데이터그램 단위로 처리하는 프로토콜

1.2 특징

 - 비연결형 서비스로 데이터그램 방식을 제공

 - 정보를 주고 받을 때 신호절차를 거치지 않음

 - UDP헤더를 보면 CheckSum 필드가 있음

   - 최소한의 오류만 잡음(검출?)

 - 낮은 신뢰성

 - TCP보다 속도가 빠름

1.3 UDP Server

 - 연결이라는 개념이 없음

 - 데이터 경계가 있음

 - 전송 순서를 보장X

 - 분실에 대한 책임이 없음

   - 일단 보내고 생각

 - 단순하기 때문에 속도가 상대적으로 좋음

 

2. UDP server

2.1 TCP Code

 - https://choiprogramming.tistory.com/101

 

[SEVER] TCP Server

1. TCP 1.1 TCP의 의미 - 인터넷상에서 데이터를 메세지의 형태로 보내기 위해 IP를 함께 사용하는 프로토콜 1.2 특징 - 연결 지향 방식 - 3-way handshaking과정을 통해 연결 설정 및 4-way handshaking을 통해

choiprogramming.tistory.com

 - TCP와 비슷하지만 연결을 받는 상태가 없어짐 (Listen)

 - 클라로 부터 받는 단계가 사라짐 (accept)

2.2 UDP Server

- 2.1에서 말했듯이 listen, accept 삭제

int main()
{
	WSADATA Init;
	if (::WSAStartup(MAKEWORD(2, 2), &Init) != 0) return 0;

	SOCKET listenSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (listenSocket == INVALID_SOCKET) return 0;

	SOCKADDR_IN serverAddr;
	::memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = ::htonl(INADDR_ANY);
	serverAddr.sin_port = ::htons(7777);

	if (::bind(listenSocket, reinterpret_cast<SOCKADDR*>(&serverAddr), sizeof(serverAddr)) == SOCKET_ERROR) return 0;
	// listen - 연결을 받기위한 상태가 없어짐

	while (true)
	{
		SOCKADDR_IN clientAddr;
		::memset(&serverAddr, 0, sizeof(serverAddr));
		int32 addrLength = sizeof(clientAddr);
		// 클라로 부터 받는 단계가 사라짐
	}

	::WSACleanup();
}

2.3 Recv From

 - TCP는 recv를 사용하여 클라이언트가 보낸 값을 확인하였지만 UDP에서는 recvfrom을 사용

int main()
{
	// listen - 연결을 받기위한 상태가 없어짐
	while (true)
	{
		// 클라로 부터 받는 단계가 사라짐		
		char recvBuffer[MAX_BUFFER];
		int32 recvLength = ::recvfrom(listenSocket, recvBuffer, sizeof(recvBuffer), 0
			, reinterpret_cast<SOCKADDR*>(&clientAddr), &addrLength);
		if (recvLength <= 0) return 0;
		cout << recvBuffer << endl;
	}
}

 

3. UDP Client

int main()
{
	// WSA 생성
	WSADATA Init;
	if (::WSAStartup(MAKEWORD(2, 2), &Init) != 0) return 0;

	// 소켓 생성
	SOCKET clientSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (clientSocket == INVALID_SOCKET) return 0;

	// 서버 주소 및 포트 생성
	SOCKADDR_IN serverAddr;
	::memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	::inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
	serverAddr.sin_port = ::htons(7777);

	// 서버와 연결이 사라짐
	while (true)
	{
		char sendBuffer[MAX_BUFFER] = "TEST SERVER";
		// 서버에게 메세지를 보냄
		int32 sendLength = ::sendto(clientSocket, sendBuffer, sizeof(sendBuffer), 0
			, reinterpret_cast<SOCKADDR*>(&serverAddr), sizeof(serverAddr));
		if (sendLength <= SOCKET_ERROR) return 0;

		this_thread::sleep_for(1s);
	}
}