[네트워크 프로그래밍] 6. 논블로킹 소켓

유기태·2023년 11월 25일
0

서버

#include<WinSock2.h>
#include<mswsock.h>
#include<ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")

void HandleError(const char* cause)
{
	int32 err = WSAGetLastError();
	cout << cause << err << " : error exists";
}

int main()
{
	WSADATA wsaData;
	int32 err;
	err = ::WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (err != 0)
	{
		cout << "Winsock Initialize Failed\n" << err << " : error exists";
		return 0;
	}

	// 블로킹
	// accept -> 접속한 클라가 있을 때 성공
	// connect -> 클라가 접속에 성공했을 때
	// send sentto -> 요청한 데이터를 송신 버퍼에 복사했을 때
	// recv recvfrom -> 수신 버퍼에 있는 내용을 유저 레벨 버퍼에 복사했을 때
	// 논블로킹
	SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
	if (listenSocket == INVALID_SOCKET)
	{
		HandleError("Socket Failed");
		return 0;
	}

	u_long on = 1;
	if (::ioctlsocket(listenSocket, FIONBIO, &on) == INVALID_SOCKET)
	{
		HandleError("Nonblocking Socket Failed");
		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);

	err = ::bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));

	if (err == SOCKET_ERROR)
	{
		HandleError("Bind failed");
		return 0;
	}

	err = ::listen(listenSocket, 15);
	if (err == SOCKET_ERROR)
	{
		HandleError("Listen failed");
		return 0;
	}

	cout << "Accept" << endl;

	SOCKADDR_IN clientAddr;
	::memset(&clientAddr, 0, sizeof(clientAddr));
	int addrLen = sizeof(clientAddr);

	// Accept
	while (true)
	{
		SOCKET clientSocket = ::accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen);
		if (clientSocket == INVALID_SOCKET)
		{
			// 원래 블록해야할  .. 너가 논 블로킹으로 하라메
			if (::WSAGetLastError() == WSAEWOULDBLOCK)
				continue;

			// Error
			break;
		}

		cout << "Client Connected!" << endl;

		while (true)
		{
			char recvBuffer[1000];
			int32 recvLen = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
			if (recvLen == SOCKET_ERROR)
			{
				if (::WSAGetLastError() == WSAEWOULDBLOCK)
					continue;

				break;
			}
			else if (recvLen == 0)
			{
				break;
			}

			cout << "Recv Data Len = " << recvLen << endl;

			// send
			while (true)
			{
				err = ::send(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
				if (err == SOCKET_ERROR)
				{
					if (::WSAGetLastError() == WSAEWOULDBLOCK)
						continue;
					
					break;
				}

				cout << "Send Data! Len = " << recvLen << endl;
				break;
			}
		}
	}
	
	// 소켓 리소스 반환
	::closesocket(listenSocket);

	// winsock 해제
	::WSACleanup();

	return 0;
}

클라이언트

#include <WinSock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")

void HandleError(const char* cause)
{
	int32 err = WSAGetLastError();
	cout << cause << err << " : error exists";
}

int main()
{

	WSADATA wsaData;
	int32 err;
	err = ::WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (err != 0)
	{
		cout << "Winsock Initialize Failed\n" << err << " : error exists";
		return 0;
	}

	SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);
	if (clientSocket == INVALID_SOCKET)
	{
		HandleError("Socket Failed");
		return 0;
	}

	u_long on = 1;
	if (::ioctlsocket(clientSocket, FIONBIO, &on) == INVALID_SOCKET)
	{
		HandleError("Nonblocking Socket Failed");
		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)
	{
		err = ::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
		if (err == SOCKET_ERROR)
		{
			if (::WSAGetLastError() == WSAEWOULDBLOCK)
				continue;

			if (::WSAGetLastError() == WSAEISCONN)
				break;
			break;
		}
	}

	cout << "Connecting Server!\n";

	char sendBuffer[1000] = "Hello World!";
	while (true)
	{
		err = ::send(clientSocket, sendBuffer, sizeof(sendBuffer), 0);
		if (err == SOCKET_ERROR)
		{
			if (::WSAGetLastError() == WSAEWOULDBLOCK)
				continue;
			break;
		}

		cout << "Send Data! Len = " << sizeof(sendBuffer) << endl;

		while (true)
		{
			char recvBuffer[1000];
			err = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
			if (err == SOCKET_ERROR)
			{
				if (::WSAGetLastError() == WSAEWOULDBLOCK)
					continue;

				break;
			}
			else if (err == 0)
			{
				break;
			}

			cout << "Recv Data! Len = " << sizeof(sendBuffer) << endl;
			cout << "Recv Data = " << recvBuffer << endl;
			break;
		}
		this_thread::sleep_for(1s);
	}
	// winsock 해제
	::WSACleanup();
}

Non_blocking socket Setting

u_long on = 1;
if (::ioctlsocket(listenSocket, FIONBIO, &on) == INVALID_SOCKET)
{
	HandleError("Nonblocking Socket Failed");
	return 0;
}

Non_blocking Error

::WSAGetLastError() == WSAEWOULDBLOCK
profile
게임프로그래머 지망!

0개의 댓글