Client와 Server가 연결되면 아래와 같이 Kernel 영역에 Recv, Send Buffer가 생성된다.
|   Client   |           |   Server   |
|            |           |            |
|            |           |            |
|            |           |            |
--------------           --------------	
|   Kernel   |           |   Kernel   |
|            |           |            |
|  Recv Buf  |           |  Recv Buf  |
|  Send Buf  |           |  Send Buf  |
|            |           |            |
--------------           --------------
// 만약 Send를 한다고 하면 Client가 직접 Server로 보내는 것이 아니라
// Send Buf에 데이터를 채우게 된다.
// 따라서 아래에 나오겠지만 Send를 한다고해서 코드가 블럭이 되지않는다
	// (단순 Send Buf에 데이터를 옮기기만 했기에)
|   Client             |           |   Server   |
|                      |           |            |
|                      |           |            |
|                      |           |            |
------------------------           --------------
|   Kernel             |           |   Kernel   |
|                      |           |            |
|  Recv Buf            |           |  Recv Buf  |
|  Send Buf[SendData]  |           |  Send Buf  |
|                      |           |            |
------------------------           --------------
// 반대로 Recv를 했다면?
// Recv Buffer에서 데이터를 긁어온다.
// 없다면 무한대기를 하게된다.
|   Client   |           |   Server             |
|            |           |                      |
|            |           |                      |
|            |           |                      |
--------------           ------------------------
|   Kernel   |           |   Kernel             |
|            |           |                      |
|  Recv Buf  |           |  Recv Buf[RecvData]  |
|  Send Buf  |           |  Send Buf            |
|            |           |                      |
--------------           ------------------------
// 만약 Send Buf가 다 차버린 상황이라면?
// Send Buf에 자리가 날때까지 코드가 대기하게된다.
|   Client                 |           |   Server   |
|                          |           |            |
|   [SendData]             |           |            |
|                          |           |            |
----------------------------           --------------
|   Kernel                 |           |   Kernel   |
|                          |           |            |
|  Recv Buf                |           |  Recv Buf  |
|  Send Buf[SendDataFull]  |           |  Send Buf  |
|                          |           |            |
----------------------------           --------------
그런데 이런식으로 코드가 블럭되는 형태로 게임을 구현하는게 좋은방법일까??
 그에 대한 설명은 다음강좌에서 진행
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;
	if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		return 0;
	SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);
	if (clientSocket == INVALID_SOCKET)
	{
		int32 errCode = ::WSAGetLastError();
		cout << "Socket ErrorCode : " << errCode << endl;
		return 0;
	}
	SOCKADDR_IN serverAddr; // IPv4
	::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); // 80 : HTTP
	if (::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
	{
		int32 errCode = ::WSAGetLastError();
		cout << "Connect ErrorCode : " << errCode << endl;
		return 0;
	}
	// ---------------------------
	// 연결 성공! 이제부터 데이터 송수신 가능!
	cout << "Connected To Server!" << endl;
	while (true)
	{
		// TODO
		char sendBuffer[100] = "Hello World!";
        // 100바이트 * 10 = 1000바이트를 거의 한 순간에 보내게 된다.
		for (int32 i = 0; i < 10; i++)
		{
			int32 resultCode = ::send(clientSocket, sendBuffer, sizeof(sendBuffer), 0);
            // 서버에서 recv를 하지 않아도 아래로 내려간다(블락이 안됨)
			if (resultCode == SOCKET_ERROR)
			{
				int32 errCode = ::WSAGetLastError();
				cout << "Send ErrorCode : " << errCode << endl;
				return 0;
			}
		}
		
		cout << "Send Data! Len = " << sizeof(sendBuffer) << endl;
		/*
		char recvBuffer[1000];
		int32 recvLen = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
        // 여기서 데이터를 받지 않으면 무한대기
		if (recvLen <= 0)
		{
			int32 errCode = ::WSAGetLastError();
			cout << "Recv ErrorCode : " << errCode << endl;
			return 0;
		}
		cout << "Recv Data! Data = " << recvBuffer << endl;
		cout << "Recv Data! Len = " << recvLen << endl;
		*/
		this_thread::sleep_for(1s);
	}
	// ---------------------------
	// 소켓 리소스 반환
	::closesocket(clientSocket);
	// 윈속 종료
	::WSACleanup();
}
Server측 데이터 받기
#include "pch.h"
#include <iostream>
#include "CorePch.h"
#include <atomic>
#include <mutex>
#include <windows.h>
#include <future>
#include "ThreadManager.h"
#include <winsock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
	WSAData wsaData;
	if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		return 0;
	SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
	if (listenSocket == INVALID_SOCKET)
	{
		int32 errCode = ::WSAGetLastError();
		cout << "Socket ErrorCode : " << errCode << endl;
		return 0;
	}
	SOCKADDR_IN serverAddr; // IPv4
	::memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = ::htonl(INADDR_ANY); //< 니가 알아서 해줘
	serverAddr.sin_port = ::htons(7777); // 80 : HTTP
	if (::bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
	{
		int32 errCode = ::WSAGetLastError();
		cout << "Bind ErrorCode : " << errCode << endl;
		return 0;
	}
	// 영업 시작!
	if (::listen(listenSocket, 10) == SOCKET_ERROR)
	{
		int32 errCode = ::WSAGetLastError();
		cout << "Listen ErrorCode : " << errCode << endl;
		return 0;
	}
	// -----------------------------
	while (true)
	{
		SOCKADDR_IN clientAddr; // IPv4
		::memset(&clientAddr, 0, sizeof(clientAddr));
		int32 addrLen = sizeof(clientAddr);
		SOCKET clientSocket = ::accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen);
		if (clientSocket == INVALID_SOCKET)
		{
			int32 errCode = ::WSAGetLastError();
			cout << "Accept ErrorCode : " << errCode << endl;
			return 0;
		}
		// 손님 입장!
		char ipAddress[16];
		::inet_ntop(AF_INET, &clientAddr.sin_addr, ipAddress, sizeof(ipAddress));
		cout << "Client Connected! IP = " << ipAddress << endl;
		// TODO
		while (true)
		{
			char recvBuffer[1000];
			this_thread::sleep_for(1s);
            // 100바이트 * 10 = 1000바이트를 거의 한 순간에 보냈는데
            // 100바이트씩 10번 들어올까??
            // Nope! = 1000바이트로 들어온다.
            // RecvBuffer를 이용하기 때문!
            // 여기서 또 생기는 문제는 1000바이트로 들어온 데이터를 어떻게 송신자가 보낸 형태로 잘 자르냐이다(다음에 설명)
			int32 recvLen = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
			if (recvLen <= 0)
			{
				int32 errCode = ::WSAGetLastError();
				cout << "Recv ErrorCode : " << errCode << endl;
				return 0;
			}
			cout << "Recv Data! Data = " << recvBuffer << endl;
			cout << "Recv Data! Len = " << recvLen << endl;
			/* 에코서버
            int32 resultCode = ::send(clientSocket, recvBuffer, recvLen, 0);
			if (resultCode == SOCKET_ERROR)
			{
				int32 errCode = ::WSAGetLastError();
				cout << "Send ErrorCode : " << errCode << endl;
				return 0;
			}*/
		}
	}
	// -----------------------------
	// 윈속 종료
	::WSACleanup();
}