• Server
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
#define _WINSOCK_DEPRECATED_NO_WARNINGS

using namespace std;

Pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib"
int main(a)
{
	WORD version = MAKEWORD(2.2);
	WSADATA data;
	WSAStartup(version, &data);

	// Create socket
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	// Bind the listening network port
	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567);
	_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	int ret = bind(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in));
	if (SOCKET_ERROR == ret)
	{
		cout << "Failed to bind port" << endl;
		return - 1;
	}
	cout << "Bond port successfully" << endl;
	if (SOCKET_ERROR == listen(_sock, 5))
	{
		cout << "Listening failed." << endl;
		return - 1;
	}
	cout << "Listening successful." << endl;

	// Waiting to receive a client connection
	sockaddr_in client_addr = {};
	int nRecvLen = sizeof(sockaddr_in);
	SOCKET _client = INVALID_SOCKET;
	char buf[] = "hello,client";
	cout << strlen(buf) << endl;
	while (true)
	{
		_client = accept(_sock, (sockaddr *)&client_addr, &nRecvLen);
		if (_client == INVALID_SOCKET)
		{
			cout << "Invalid SOCKET" << endl;
		}
		// Get the client address
		cout << "New client added, IP:" << inet_ntoa(client_addr.sin_addr) << endl;
		send(_client, buf, strlen(buf) + 1.0); // Add the terminator
	}
	/ / close the socket
	closesocket(_sock);
	WSACleanup(a);return 0;
}
Copy the code
  • client
#include <WinSock2.h>
#include <windows.h>
#include <iostream>

//#define _WINSOCK_DEPRECATED_NO_WARNINGS
using namespace std;
Pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib"
int main(a)
{
	WORD version = MAKEWORD(2.2);
	WSADATA data;
	WSAStartup(version, &data);
	SOCKET _sock = socket(AF_INET,SOCK_STREAM,0);
	if (SOCKET_ERROR == _sock) 
	{
		cout << "Bond port successfully" << endl;
		return - 1;
	}
	sockaddr_in _sin = {}; // Address of the server to be connected
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567);
	_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	if (SOCKET_ERROR == connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in)))
	{
		cout << "Connection failed" << endl;
		return - 1;
	}
	cout << "Server connection successful" << endl;
	
	while (true)
	{
		char cmdBuf[1024] = {};
		scanf("%s", cmdBuf);
		if (0= =strcmp(cmdBuf, "exit"))
		{
			break;
		}
		else
		{
			send(_sock, cmdBuf, strlen(cmdBuf)+1 ,0);
		}
		char recv_buf[1024] = {};
		int nLen = recv(_sock, recv_buf, 1024.0);
		cout << "nLen = " << nLen << endl;
		if (nLen > 0)
		{
			cout << "Received data:"<< recv_buf << endl; }}/ / close the socket
	closesocket(_sock);
	WSACleanup(a);return 0;
}
Copy the code

Structure strong binary stream

struct Data{
    int code;
    char  name[256];
}

Data data = {1."wang"};
send(socket,(const char *)&data,strlen(data)+1.0);
Copy the code

When there are multiple services, the server receives the data and has no way of knowing which structure object to force the binary stream into. In network communication, a packet usually contains a packet header and a packet body. We can construct a structure whose packet header describes the packet body.

eg:

emun CMD
{
    CMD_LOGIN,
    CMD_LOGIN_RESULT,
    CMD_LOGOUT,
    CMD_LOGOUT_RESULT,
    ERROR
}
struct DataHeader
{
    int dataLength;
    int cmd;
}
struct Login : public DataHeader
{
    Login()
    {
    	dataLength = sizeof(Login);
    	cmd = CMD_LOGIN;
    }
    char username[32];
    char password[32];
}
Copy the code

The server reads recV data in two times. The first time the request header is read, the second time the header information is read the request body of the specified length. Make a simple change to the above code:

  • server
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
#define _WINSOCK_DEPRECATED_NO_WARNINGS

using namespace std;

Pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib"

enum CMD
{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};
struct DataHeader
{
	int dataLength;
	int cmd;
};
struct Login : public DataHeader
{
	Login()
	{
		dataLength = sizeof(Login);
		cmd = CMD_LOGIN;
	}
	char username[32];
	char password[32];
};

struct LoginResult : public DataHeader
{
	LoginResult()
	{
		dataLength = sizeof(LoginResult);
		cmd = CMD_LOGIN_RESULT;
		result = 0;
	}
	int result;
};

struct Logout : public DataHeader
{
	Logout()
	{
		dataLength = sizeof(Logout);
		cmd = CMD_LOGOUT;
	}
	char username[32];
};

struct LogoutResult : public DataHeader
{
	LogoutResult()
	{
		dataLength = sizeof(LogoutResult);
		cmd = CMD_LOGOUT;
		result = 0;
	}
	int result;
};

int main(a)
{
	WORD version = MAKEWORD(2.2);
	WSADATA data;
	WSAStartup(version, &data);

	// Create socket
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	// Bind the listening network port
	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567);
	_sin.sin_addr.S_un.S_addr = ADDR_ANY;

	if (SOCKET_ERROR == bind(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in)))
	{
		cout << "Failed to bind port" << endl;
		return - 1;	
	}
	cout << "Bond port successfully" << endl;

	if (SOCKET_ERROR == listen(_sock, 5))
	{
		cout << "Listening failed." << endl;
		return - 1;
	}
	cout << "Listening successful." << endl;
		

	// Waiting to receive a client connection
	sockaddr_in client_addr = {};
	int nRecvLen = sizeof(sockaddr_in);
	cout << "nRecvLen = " << nRecvLen << endl;
	SOCKET _client = - 1;
	char recvBuf[1024] = {};

	_client = accept(_sock, (sockaddr *)&client_addr, &nRecvLen);
   if (_client == INVALID_SOCKET)
	{
    	cout << "Invalid SOCKET" << endl;
	}
	// Get the client address
	cout << "New client added, IP:" << inet_ntoa(client_addr.sin_addr) << endl;

	while (true) 
	{
		// Use a buF to receive the data in the request header first
		char szRecv[1024] = {};
		int nLen = recv(_client, (char*)&szRecv, sizeof(DataHeader),0);
		DataHeader* header = (DataHeader*)szRecv;
		
		if (nLen <= 0)
		{
			cout << "Client has exited." << endl;
			break;
		}
		// cout << "received command" << recvBuf << endl;

		switch (header->cmd)
		{
			case CMD_LOGIN:
			{
				recv(_client, szRecv +sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
				Login* login = (Login*)szRecv;
				cout << "Received data: CMD_LOGIN, length:" << login->dataLength << ",username:" << login->username << ",password" << login->password << endl;
				LoginResult loginRes = {};
				send(_client,(const char*)&loginRes,sizeof(loginRes),0);
				break;
			}
			case CMD_LOGOUT:
			{
				
				recv(_client, szRecv +sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
				Logout* logout =  (Logout*)szRecv;
				cout << "Received data: CMD_LOGOUT, length:" << logout->dataLength << ",username:" << logout->username  << endl;
				LogoutResult logoutRes = {};
				send(_client, (const char*)&logoutRes, sizeof(logoutRes), 0);
				break;
			}
			default:
				DataHeader header = { 0,CMD_ERROR };
				/*header->cmd = CMD_ERROR; header->dataLength = 0; * /
				send(_client, (const char*)&header, sizeof(header), 0);
				break; }}/ / close the socket
	closesocket(_sock);
	WSACleanup(a);return 0;
}
Copy the code
  • client
#include <WinSock2.h>
#include <windows.h>
#include <iostream>

//#define _WINSOCK_DEPRECATED_NO_WARNINGS
using namespace std;
Pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib"

enum CMD
{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};
struct DataHeader
{
	int dataLength;
	int cmd;
};
struct Login : public DataHeader
{
	Login()
	{
		dataLength = sizeof(Login);
		cmd = CMD_LOGIN;
	}
	char username[32];
	char password[32];
};

struct LoginResult : public DataHeader
{
	LoginResult()
	{
		dataLength = sizeof(LoginResult);
		cmd = CMD_LOGIN_RESULT;
		result = 0;
	}
	int result;
};

struct Logout : public DataHeader
{
	Logout()
	{
		dataLength = sizeof(Logout);
		cmd = CMD_LOGOUT;
	}
	char username[32];
};

struct LogoutResult : public DataHeader
{
	LogoutResult()
	{
		dataLength = sizeof(LogoutResult);
		cmd = CMD_LOGOUT;
		result = 0;
	}
	int result;
};

int main(a)
{
	WORD version = MAKEWORD(2.2);
	WSADATA data;
	WSAStartup(version, &data);
	SOCKET _sock = socket(AF_INET,SOCK_STREAM,0);
	if (SOCKET_ERROR == _sock) 
	{
		cout << "Bond port successfully" << endl;
		return - 1;
	}
	sockaddr_in _sin = {}; // Address of the server to be connected
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567);
	_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	if (SOCKET_ERROR == connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in)))
	{
		cout << "Connection failed" << endl;
		return - 1;
	}
	cout << "Server connection successful" << endl;
	while (true)
	{
		char cmdBuf[1024] = {};
		scanf("%s", cmdBuf);
		if (0= =strcmp(cmdBuf, "login"))
		{
			Login login;
			strcpy(login.username,"scott");
			strcpy(login.password,"123456");
			send(_sock, (const char*)&login, sizeof(login), 0);

			// Receive the return value
			LoginResult loginRes = {};
			recv(_sock,(char*)&loginRes,sizeof(loginRes),0);
			cout << "Return value:" << loginRes.result << endl;
		}
		else if (0= =strcmp(cmdBuf, "logout"))
		{
			Logout logout = {};
			strcpy(logout.username, "scott");
			send(_sock, (const char*)&logout, sizeof(logout), 0);

			// Receive the return value
			LogoutResult logoutRes = {};
			recv(_sock, (char*)&logoutRes, sizeof(logoutRes), 0);
			cout << "Return value:" << logoutRes.result << endl;
		}
		else if (0= =strcmp(cmdBuf, "exit"))
		{
			cout << "Stop connection" << endl;
			break;
		}
		else 
		{
			cout << "Input error instruction" << endl;
			break; }}/ / close the socket
	closesocket(_sock);
	WSACleanup(a);return 0;
}
Copy the code

The Base version is all that, but blocking singlet, which is definitely not possible in real development, and we need a way to send and receive messages that doesn’t block all the time.