티스토리 뷰

IT/Network

[WinSock2] UDP Echo 서버(v1.0)

주인장 진빼이

에코 서버(Echo Server)란 ?

서버는 클라이언트가 송신한 데이터 크기만큼 수신하여 다시 클라이언트에게 그 크기만큼 재송신하는 것이다.

 

프로그램 설명

UDP 프로토콜을 이용한 에코서버 및 클라이언트 프로그램 소스코드이다.

UDP 프로토콜은 TCP 프로토콜과 다르게 1:1이 아닌 1:N 통신이 가능하다. 소켓에 접속을 대기하지도 않는다.

또한 데이터의 경계가 없으므로 데이터 호출 횟수에 대해 동일하게 맞춰줘야할 필요가 있다.

프로그램 전반적으로 WBCS 문자열 데이터 처리를 하지 않았으며, MBCS 문자셋을 이용하여 문자열을 출력하고 있다.

 

 

클라이언트는 표준 입력(stdin)을 이용해 사용자에게 텍스트 내용을 입력받으며, 개행문자를 포함하여 서버에게 송신하고 있다.

클라이언트는 패킷을 수신할 때 데이터 크기만큼 수신하게 되는데 서버에서 재송신된 패킷은 송신한 데이터 크기 정보를 가지고 있지 않는다 그러므로 클라이언트는 패킷 송신 후  sendto 함수에서 반환하는 송신한 데이터 크기 정보를 이용하여 그 크기만큼 데이터를 수신하고 있다.

//==== Server ====

#include <iostream>

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <tchar.h>

#define BUF_SIZE 30
using namespace std;
int main()
{
	cout << "====== SERVER ======\n";
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	//socket bind
	SOCKET hServSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

	SOCKADDR_IN servAddr = { 0, };
	servAddr.sin_port = htons(9000);
	servAddr.sin_family = AF_INET;
	InetPton(AF_INET, _T("127.0.0.1"), &servAddr.sin_addr);

	size_t addrSize = sizeof(SOCKADDR_IN);

	if (bind(hServSock, (LPSOCKADDR)&servAddr, addrSize) == SOCKET_ERROR)
	{
		cout << "bind error";
		exit(0);
	}

	SOCKADDR_IN clntAddr = { 0, };
	int recvLength = 0;
	char message[BUF_SIZE];
	while (1)
	{
		int clntAddrSize = sizeof(clntAddr);
		recvLength = recvfrom(hServSock, message, BUF_SIZE, 0, (LPSOCKADDR)&clntAddr, &clntAddrSize);
		
		sendto(hServSock, message, recvLength, 0, (LPSOCKADDR)&clntAddr, clntAddrSize);
		message[recvLength] = 0;;
		cout << message;
	}
	closesocket(hServSock);
	WSACleanup();
	return 0;
}

 

//==== Client ====
#include <iostream>

#include <tchar.h>
#include <WinSock2.h>
#include <WS2tcpip.h>

#define BUF_SIZE 30
using namespace std;
int main()
{

	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	SOCKET hServSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (hServSock == INVALID_SOCKET)
	{
		cout << "socket error!";
		exit(0);
	}

	SOCKADDR_IN servAddr = { 0, };
	servAddr.sin_family = AF_INET;
	servAddr.sin_port = htons(9000);
	InetPton(AF_INET, _T("127.0.0.1"), &servAddr.sin_addr);

	char message[BUF_SIZE];
	SOCKADDR_IN recvAddr;
	int recvAddrSize = sizeof(recvAddr);
	int sendLength = 0;
	while (1)
	{
		cout << "Input Text: ";
		fgets(message, sizeof(message), stdin);

		if (!strcmp(message, "quit\n") || !strcmp(message, "QUIT\n"))
			break;

		sendLength = sendto(hServSock, message, strlen(message), 0, (LPSOCKADDR)&servAddr, sizeof(servAddr));
		recvfrom(hServSock, message, sendLength, 0, (LPSOCKADDR)&recvAddr, &recvAddrSize);
		
		message[sendLength] = 0;
		cout << "Recive: " << message;
		cout << "\n";
	}
    
	WSACleanup();
	return 0;
}

 

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함