MMOServer

Non-Blocking Socket(C++)

이야기prog 2025. 4. 2. 23:50

client

 

#include "pch.h"
#include <iostream>

#include <WinSock2.h>
#include <MSWSock.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
	//윈도우 소켓 초기화
	// 관련 정보가 wsaData에 채워짐
	WSADATA wsaData;
	if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		return 0;

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

	u_long on = 1;
	if (::ioctlsocket(clientSocket, FIONBIO, &on) == INVALID_SOCKET) // non-block
		return 0;

	SOCKADDR_IN serverAddr;

	serverAddr.sin_family = AF_INET;
	::inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
	serverAddr.sin_port = ::htons(7777);

	//connect
	while (true) {
		if (::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
			if (::WSAGetLastError() == WSAEWOULDBLOCK) {
				continue;
			}

			if (::WSAGetLastError() == WSAEISCONN) // 이미 connect되었는데 또 시도
				break;

			//ERROR
			break;
		}
	}
	cout << "Server Connect!" << endl;

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

			//ERROR
			break;
		}

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

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

				//ERROR
				break;
			}
			else if (recvLen == 0) {
				//연결 끊김
				break;
			}

			cout << "recvLen: " << recvLen << endl;
			break;
		}

		this_thread::sleep_for(1s);
	}
	::closesocket(clientSocket); // 소켓 리소스 반환
	::WSACleanup(); // 윈속 종료
}

 

 

server

 

#include "pch.h"
#include <thread>
#include <atomic>
#include <mutex>
#include <future>
#include "CorePch.h"
#include "ThreadManager.h"
#include "RefCounting.h"
#include "Memory.h"
#include "TypeCast.h"

#include <WinSock2.h>
#include <MSWSock.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

void HandleError(const char* str) {
	int32 errCode = ::WSAGetLastError();
	cout << str << " erroCode: " << errCode << endl;
}
int main() {
	//윈도우 소켓 초기화
// 관련 정보가 wsaData에 채워짐
	WSADATA wsaData;
	if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		return 0;

	SOCKET serverSocket = ::socket(AF_INET, SOCK_STREAM, 0);
	if (serverSocket == INVALID_SOCKET) {
		return 0;
	}

	u_long on = 1;
	if (::ioctlsocket(serverSocket, FIONBIO, &on) == INVALID_SOCKET) // non-block
		return 0;

	SOCKADDR_IN serverAddr;

	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = ::htonl(INADDR_ANY);
	serverAddr.sin_port = ::htons(7777);

	if (::bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
		return 0;

	if (::listen(serverSocket, 10) == SOCKET_ERROR)
		return 0;

	cout << "Accept" << endl;
	SOCKADDR_IN clientAddr;
	::memset(&clientAddr, 0, sizeof(clientAddr));
	int32 clientLen = sizeof(clientAddr);
	while (true) {

		SOCKET clientSocket = ::accept(serverSocket, (SOCKADDR*)&clientAddr, &clientLen);
		if (clientSocket == INVALID_SOCKET) {
			if (::WSAGetLastError() == WSAEWOULDBLOCK) { // 논블록이라서 들어온 부분
				continue;
			}

			//error
			break;
		}
		char ipAddress[16];
		::inet_ntop(AF_INET, &clientAddr, ipAddress, sizeof(ipAddress));
		cout << "Client Connect!, IP: " << ipAddress << endl;

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

			if (recvLen == SOCKET_ERROR) {
				if (::WSAGetLastError() == WSAEWOULDBLOCK)
					continue;

				//Error
				break;
			}
			else if (recvLen == 0) {
				//연결 끊김
				break;
			}

			cout << "recvLen: " << recvLen << endl;

			// send
			while (true) {
				if (::send(clientSocket, recvBuffer, recvLen, 0) == SOCKET_ERROR) {
					if (::WSAGetLastError() == WSAEWOULDBLOCK)
						continue;

					//Error
					break;
				}

				cout << "Send Data Len: " << recvLen << endl;
				break;
			}
		}
	}

	
	::closesocket(serverSocket); // 소켓 리소스 반환
	::WSACleanup(); // 윈속 종료
	return 0;
}

'MMOServer' 카테고리의 다른 글

WSA(window socket api)EventSelect (c++)  (0) 2025.04.03
Socket_select방식(C++)  (0) 2025.04.03
sockopt(C++)  (0) 2025.04.02
UDP(C++)  (0) 2025.04.01
TCP(C++)  (0) 2025.04.01