服务端与客户端1.2——发送结构化消息

服务端与客户端1.2——发送结构化消息,第1张

上节服务端与客户端1.1——持续处理“单个客户端”发送的请求_贪睡的蜗牛的博客-CSDN博客 

目录

使用结构体进行传递数据1.21

使用网络数据报文(增加数据头)1.22

服务端修改

客户端修改

网络数据报文一次发送1.23

客户端代码

服务器修改后代码

使用dataLength来明确具体需要接收多少1.24

服务端修改后的代码



上节是使用字符串的形式充当的请求命令,使用getName获得名字,使用getAge获得年龄,其他命令统一用一个信息进行回复。本节将改进字符串的消息传递方式, 构建结构化的网络消息,使网络传输功能更复杂。这里我们使用结构体,一次性的将数据全部传递

使用结构体进行传递数据1.21
 

一定要保证服务端和客户端( *** 作系统)中 

   数据结构字节序和大小保证一致    内存对齐(要求结构体里的变量的相对顺序是一样的)

添加结构体

服务端和客户端统一添加同一个结构体,然后交互时传递的是这个结构体

struct DataPackage
{
	int age;
	char name[32];
};

服务端,将getAge和getName统一命令为getInfo

if (0 == strcmp(_recvBuf, "getInfo"))
{
	DataPackage dp = { 24,"Evila" };
	send(_clientSock, (const char*)&dp, sizeof(DataPackage), 0);
}

客户端,将返回数据后进行修改

//6. 接受服务器信息 recv
		char recvBuf[256] = {};
		int nlen = recv(_sock, recvBuf, sizeof(recvBuf), 0); //返回值是接收数据的长度
		if (nlen > 0)
		{
			DataPackage* pDP = (DataPackage*)recvBuf;
			cout << "接收到数据: 年龄=" << pDP->age << ",名字=" << pDP->name << endl;
		}

注意,这样将会导致如果不是返回的DataPackage结构体,将会出现问题

使用网络数据报文(增加数据头)1.22

本节是先传递数据头,然后再传递结构体

报文有两个部分,包头和包体,是网络消息的基本单元

包头:描述本次消息包的大小(比如固定前4个字节表示报文的大小)
包体:数据内容

传输数据时,客户端发送请求应先发送 包头 再发送包体; 服务器端接收请求时,先接收请求头,再接收请求体;同样的,服务器端返回时和客户端接收时。

这里枚举下命令,添加消息头结构体,添加登录、退出登录、登录结果,退出登录结果四个结构体

下列枚举,从0开始的 

enum CMD  //消息枚举
{
	CMD_LOGIN,
	CMD_LOGINOUT,
	CMD_ERROR
};
//消息头
struct DataHeader
{
	short dataLength;    //数据长度 32767字节
	short cmd;
};

struct Login
{
	char userName[32];
	char Password[32];
};
struct Logout
{
	char userName[32];
};
struct LoginResult
{
	int result;
};
struct LogoutResult
{
	int result;
};
服务端修改

服务端在收到DataHeader(里面包含cmd),判断cmd是啥,然后做出处理,先返回一个头,再返回处理结果(这里的头用客户端请求来的头)

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库


enum CMD  //消息枚举
{
	CMD_LOGIN,
	CMD_LOGINOUT,
	CMD_ERROR
};
//消息头
struct DataHeader
{
	short dataLength;    //数据长度 32767字节
	short cmd;
};

struct Login
{
	char userName[32];
	char Password[32];
};
struct Logout
{
	char userName[32];
};
struct LoginResult
{
	int result;
};
struct LogoutResult
{
	int result;
};


int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///


	//(1) 用Socket API建立简易的TCP服务端

	//	1. 建立一个Socket
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // ipv4 面向字节流的 tcp协议

	//	2. 绑定接受客户端连接的端口 bind

	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567); //端口号 host to net  sockaddr_in中port是USHORT类型
								 //网络中port是 unsigend short类型 因此需要Htons进行转换
	//_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //服务器绑定的IP地址  127.0.0.1是本地地址
	_sin.sin_addr.S_un.S_addr = INADDR_ANY; //不限定访问该服务端的IP
	if (bind(_sock, (sockaddr*)&_sin, sizeof(_sin)) == SOCKET_ERROR)  //sockaddr 不利于编码  
	{
		cout << "ERROR: 绑定用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 绑定端口成功..." << endl;
	}
	//	3. 监听网络端口 listen

	if (listen(_sock, 5) == SOCKET_ERROR)//第二个参数 backbag 最大允许连接数量
	{
		cout << "ERROR: 监听用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 监听端口成功..." << endl;
	}

	//	4. 等待接受客户端连接 accept

	sockaddr_in _clientAddr = {};
	int cliendAddrLen = sizeof(_clientAddr);
	SOCKET _clientSock = INVALID_SOCKET; // 初始化无效的socket 用来存储接入的客户端

	_clientSock = accept(_sock, (sockaddr*)&_clientAddr, &cliendAddrLen);
	while (true)
	{
		DataHeader header = {};
		//5 首先接收数据包头
		int nlen = recv(_clientSock, (char*)&header, sizeof(header), 0); //接受客户端的数据 第一个参数应该是客户端的socket对象
		if (nlen <= 0)
		{
			//客户端退出
			cout << "客户端已退出,任务结束" << endl;
			break;
		}
		cout << "收到命令:" << header.cmd << "数据长度" << header.dataLength << endl;

		switch (header.cmd)
		{
		case CMD_LOGIN:
		{
			Login _login = {};
			recv(_clientSock, (char*)&_login, sizeof(Login), 0);
			//忽略判断用户名密码是否正确的过程
			LoginResult _loginres = { 1 };
			send(_clientSock, (char*)&header, sizeof(DataHeader), 0);
			send(_clientSock, (char*)&_loginres, sizeof(LoginResult), 0);
			cout << "登陆用户: " << _login.userName << endl;
		}break;
		case CMD_LOGINOUT:
		{
			Logout _logout = {};
			recv(_clientSock, (char*)&_logout, sizeof(Logout), 0);
			LogoutResult _logoutres = { 1 };
			send(_clientSock, (char*)&header, sizeof(DataHeader), 0);
			send(_clientSock, (char*)&_logoutres, sizeof(LogoutResult), 0);
			cout << "登出用户: " << _logout.userName << endl;
		}break;
		default:
			header.cmd = CMD_ERROR;
			header.dataLength = 0;
			send(_clientSock, (char*)&header, sizeof(DataHeader), 0);
			break;
		}
	}
	//	6. 关闭socket
	closesocket(_sock);
	// 清除Windows socket环境
	WSACleanup();
	return 0;
}
客户端修改

客户端先两次发送,再两次接收,两次分别都是包头和具体内容 

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库


enum CMD  //消息枚举
{
	CMD_LOGIN,
	CMD_LOGINOUT,
	CMD_ERROR
};
//消息头
struct DataHeader
{
	short dataLength;    //数据长度 32767字节
	short cmd;
};

struct Login
{
	char userName[32];
	char Password[32];
};
struct Logout
{
	char userName[32];
};
struct LoginResult
{
	int result;
};
struct LogoutResult
{
	int result;
};

int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///


	//(1) 用Socket API建立简易的TCP客户端

	//	1. 建立一个Socket  下面第三个参数不需要指定
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, 0); // ipv4 面向字节流的 tcp协议
	if (INVALID_SOCKET == _sock)
	{
		cout << "错误,建立socket失败"<> cmdBuf;
		// 4 处理请求
		if (strcmp(cmdBuf, "exit") == 0)
		{
			break;
		}
		else if (0 == strcmp(cmdBuf, "login"))
		{
			Login _login = { "Evila","Evila_Password" };
			DataHeader _header = {};
			_header.dataLength = sizeof(Login);
			_header.cmd = CMD_LOGIN;
			// 5 向服务器发送请求命令 先发送包头
			send(_sock, (const char*)&_header, sizeof(DataHeader), 0);
			//再发送包体
			send(_sock, (const char*)&_login, sizeof(Login), 0);

			//6. 接受服务器信息 recv
			//先接收 返回数据的包头
			DataHeader returnHeader = {};
			LoginResult _lgRes = {};
			recv(_sock, (char*)&returnHeader, sizeof(DataHeader), 0);
			//再接收 返回数据的包体
			recv(_sock, (char*)&_lgRes, sizeof(LoginResult), 0);
			cout << "LoginResult: " << _lgRes.result << endl;
		}
		else if (0 == strcmp(cmdBuf, "logout"))
		{
			Logout _logout = { "Evila" };
			DataHeader _header = {};
			_header.dataLength = sizeof(Logout);
			_header.cmd = CMD_LOGINOUT;
			// 5 向服务器发送请求命令 先发送包头
			send(_sock, (const char*)&_header, sizeof(DataHeader), 0);
			//再发送包体
			send(_sock, (const char*)&_logout, sizeof(Logout), 0);

			//6. 接受服务器信息 recv
			//先接收 返回数据的包头
			DataHeader returnHeader = {};
			LogoutResult _lgRes = {};
			recv(_sock, (char*)&returnHeader, sizeof(DataHeader), 0);
			//再接收 返回数据的包体
			recv(_sock, (char*)&_lgRes, sizeof(LogoutResult), 0);
			cout << "LogoutResult: " << _lgRes.result << endl;
		}
		else
		{
			cout << "不支持的命令,请重新输入。" << endl;
		}
		//放到循环中 重复接受服务器的返回信息
		//6. 接受服务器信息 recv
		//char recvBuf[256] = {};
		//int nlen = recv(_sock, recvBuf, sizeof(recvBuf), 0); //返回值是接收数据的长度
		//if (nlen > 0)
		//{
		//	DataPackage* pDP = (DataPackage*)recvBuf;
		//	cout << "接收到数据: 年龄=" << pDP->age << ",名字=" << pDP->name << endl;
		//}
		//else
		//{
		//	cout << "ERROR: 数据传输失败..." << endl;
		//}
	}





	//	6. 关闭socket
	closesocket(_sock);
	// 清除Windows socket环境
	WSACleanup();
	getchar();//防止一闪而过
	return 0;
}

网络数据报文一次发送1.23

本节是一次发送数据,大体流程是先接受请求头,根据请求头进入相应的逻辑处理,然后再接收剩下的内容 

首先在服务端,客户端补充消息枚举 

 2、对每个消息添加继承消息头

 3、注意下面内容,偏移量

客户端代码
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库


enum CMD  //消息枚举
{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGINOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};
//消息头
struct DataHeader
{
	short dataLength;    //数据长度 32767字节
	short cmd;
};

struct Login : public DataHeader
{
	Login()
	{
		dataLength = sizeof(Login);
		cmd = CMD_LOGIN;
	}
	char userName[32];
	char Password[32];
};
struct Logout :public DataHeader
{
	Logout()
	{
		dataLength = sizeof(Logout);
		cmd = CMD_LOGINOUT;
	}
	char userName[32];
};
struct LoginResult :public DataHeader
{
	LoginResult()
	{
		dataLength = sizeof(LoginResult);
		cmd = CMD_LOGIN_RESULT;
	}
	int result;
};
struct LogoutResult :public DataHeader
{
	LogoutResult()
	{
		dataLength = sizeof(LogoutResult);
		cmd = CMD_LOGOUT_RESULT;
	}
	int result;
};

int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///


	//(1) 用Socket API建立简易的TCP客户端

	//	1. 建立一个Socket  下面第三个参数不需要指定
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, 0); // ipv4 面向字节流的 tcp协议
	if (INVALID_SOCKET == _sock)
	{
		cout << "错误,建立socket失败"<> cmdBuf;
		// 4 处理请求
		if (strcmp(cmdBuf, "exit") == 0)
		{
			break;
		}
		else if (0 == strcmp(cmdBuf, "login"))
		{
			Login _login;
			strcpy_s(_login.userName, "Evila");
			strcpy_s(_login.Password, "Evila_Password");
			// 5 向服务器发送请求命令
			send(_sock, (const char*)&_login, sizeof(Login), 0);

			//6. 接受服务器信息 recv
			LoginResult _lgRes;
			recv(_sock, (char*)&_lgRes, sizeof(LoginResult), 0);
			cout << "LoginResult: " << _lgRes.result << endl;
		}
		else if (0 == strcmp(cmdBuf, "logout"))
		{
			Logout _logout;
			strcpy_s(_logout.userName, "Evila");
			// 5 向服务器发送请求命令 
			send(_sock, (const char*)&_logout, sizeof(Logout), 0);

			//6. 接受服务器信息 recv
			LogoutResult _lgRes;
			//返回数据
			recv(_sock, (char*)&_lgRes, sizeof(LogoutResult), 0);
			cout << "LogoutResult: " << _lgRes.result << endl;
		}
		else
		{
			cout << "不支持的命令,请重新输入。" << endl;
		}
	}




	//	6. 关闭socket
	closesocket(_sock);
	// 清除Windows socket环境
	WSACleanup();
	getchar();//防止一闪而过
	return 0;
}
服务器修改后代码
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库


enum CMD  //消息枚举
{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGINOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};
//消息头
struct DataHeader
{
	short dataLength;    //数据长度 32767字节
	short cmd;
};

struct Login : public DataHeader
{
	Login()
	{
		dataLength = sizeof(Login);
		cmd = CMD_LOGIN;
	}
	char userName[32];
	char Password[32];
};
struct Logout :public DataHeader
{
	Logout()
	{
		dataLength = sizeof(Logout);
		cmd = CMD_LOGINOUT;
	}
	char userName[32];
};
struct LoginResult :public DataHeader
{
	LoginResult()
	{
		dataLength = sizeof(LoginResult);
		cmd = CMD_LOGIN_RESULT;
	}
	int result;
};
struct LogoutResult :public DataHeader
{
	LogoutResult()
	{
		dataLength = sizeof(LogoutResult);
		cmd = CMD_LOGOUT_RESULT;
	}
	int result;
};


int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///


	//(1) 用Socket API建立简易的TCP服务端

	//	1. 建立一个Socket
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // ipv4 面向字节流的 tcp协议

	//	2. 绑定接受客户端连接的端口 bind

	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567); //端口号 host to net  sockaddr_in中port是USHORT类型
								 //网络中port是 unsigend short类型 因此需要Htons进行转换
	//_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //服务器绑定的IP地址  127.0.0.1是本地地址
	_sin.sin_addr.S_un.S_addr = INADDR_ANY; //不限定访问该服务端的IP
	if (bind(_sock, (sockaddr*)&_sin, sizeof(_sin)) == SOCKET_ERROR)  //sockaddr 不利于编码  
	{
		cout << "ERROR: 绑定用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 绑定端口成功..." << endl;
	}
	//	3. 监听网络端口 listen

	if (listen(_sock, 5) == SOCKET_ERROR)//第二个参数 backbag 最大允许连接数量
	{
		cout << "ERROR: 监听用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 监听端口成功..." << endl;
	}

	//	4. 等待接受客户端连接 accept

	sockaddr_in _clientAddr = {};
	int cliendAddrLen = sizeof(_clientAddr);
	SOCKET _clientSock = INVALID_SOCKET; // 初始化无效的socket 用来存储接入的客户端

	_clientSock = accept(_sock, (sockaddr*)&_clientAddr, &cliendAddrLen);
	while (true)
	{
		DataHeader header = {};
		//5 首先接收数据包头
		int nlen = recv(_clientSock, (char*)&header, sizeof(DataHeader), 0); //经过改进 包头信息已经继承到了包体中 按照内存对齐 首先读取sizeof(DataHeader)的字节序列
		if (nlen <= 0)
		{
			//客户端退出
			cout << "客户端已退出,任务结束" << endl;
			break;
		}

		switch (header.cmd)
		{
		case CMD_LOGIN:
		{
			Login _login;
			recv(_clientSock, (char*)&_login + sizeof(DataHeader), sizeof(Login) - sizeof(DataHeader), 0); //这里要注意 程序已经读取了Dataheader了,因此这里应该从_login + sizeof(DataHeader) 开始读取,读取的长度也需要剪掉包头的长度  实现传输的数据内存对齐
			cout << "收到命令:CMD_LOGIN" << " 数据长度 = " << header.dataLength << " UserName = " << _login.userName << " Password = " << _login.Password << endl;
			//忽略了判断用户名密码是否正确的过程
			LoginResult _loginres;
			send(_clientSock, (char*)&_loginres, sizeof(LoginResult), 0);
		}break;
		case CMD_LOGINOUT:
		{
			Logout _logout;
			recv(_clientSock, (char*)&_logout + sizeof(DataHeader), sizeof(Logout) - sizeof(DataHeader), 0);
			cout << "收到命令:CMD_LOGOUT" << " 数据长度 = " << header.dataLength << " UserName = " << _logout.userName << endl;
			LogoutResult _logoutres;
			send(_clientSock, (char*)&_logoutres, sizeof(LogoutResult), 0);
		}break;
		default:
			header.cmd = CMD_ERROR;
			header.dataLength = 0;
			send(_clientSock, (char*)&header, sizeof(DataHeader), 0);
			break;
		}
	}
	//	6. 关闭socket
	closesocket(_sock);
	// 清除Windows socket环境
	WSACleanup();
	return 0;
}
使用dataLength来明确具体需要接收多少1.24

dataLength的作用是告知收发文件的大小,本次改进通过使用dataLength提供的长度进行收发。

 1、创建一个缓冲区首先只接收数据头

 2、通过将数据头转换为标准数据头去判断请求的类型,然后进去相应的处理流程,继续将后续的数据读入缓冲区内 

服务端修改后的代码
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库


enum CMD  //消息枚举
{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGINOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};
//消息头
struct DataHeader
{
	short dataLength;    //数据长度 32767字节
	short cmd;
};

struct Login : public DataHeader
{
	Login()
	{
		dataLength = sizeof(Login);
		cmd = CMD_LOGIN;
	}
	char userName[32];
	char Password[32];
};
struct Logout :public DataHeader
{
	Logout()
	{
		dataLength = sizeof(Logout);
		cmd = CMD_LOGINOUT;
	}
	char userName[32];
};
struct LoginResult :public DataHeader
{
	LoginResult()
	{
		dataLength = sizeof(LoginResult);
		cmd = CMD_LOGIN_RESULT;
	}
	int result;
};
struct LogoutResult :public DataHeader
{
	LogoutResult()
	{
		dataLength = sizeof(LogoutResult);
		cmd = CMD_LOGOUT_RESULT;
	}
	int result;
};


int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///


	//(1) 用Socket API建立简易的TCP服务端

	//	1. 建立一个Socket
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // ipv4 面向字节流的 tcp协议

	//	2. 绑定接受客户端连接的端口 bind

	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567); //端口号 host to net  sockaddr_in中port是USHORT类型
								 //网络中port是 unsigend short类型 因此需要Htons进行转换
	//_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //服务器绑定的IP地址  127.0.0.1是本地地址
	_sin.sin_addr.S_un.S_addr = INADDR_ANY; //不限定访问该服务端的IP
	if (bind(_sock, (sockaddr*)&_sin, sizeof(_sin)) == SOCKET_ERROR)  //sockaddr 不利于编码  
	{
		cout << "ERROR: 绑定用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 绑定端口成功..." << endl;
	}
	//	3. 监听网络端口 listen

	if (listen(_sock, 5) == SOCKET_ERROR)//第二个参数 backbag 最大允许连接数量
	{
		cout << "ERROR: 监听用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 监听端口成功..." << endl;
	}

	//	4. 等待接受客户端连接 accept

	sockaddr_in _clientAddr = {};
	int cliendAddrLen = sizeof(_clientAddr);
	SOCKET _clientSock = INVALID_SOCKET; // 初始化无效的socket 用来存储接入的客户端

	_clientSock = accept(_sock, (sockaddr*)&_clientAddr, &cliendAddrLen);
	while (true)
	{
		//使用一个缓冲区接收数据 暂定最大收发1024个字节		后续会改进大文件的传输
		char* szRecv = new char[1024];

		//5 首先接收数据包头
		int nlen = recv(_clientSock, szRecv, sizeof(DataHeader), 0); //接受客户端的数据 第一个参数应该是客户端的socket对象
		
		if (nlen <= 0)
		{
			//客户端退出
			cout << "客户端已退出,任务结束" << endl;
			break;
		}
		//用一个指针指向这个头部
		DataHeader* header = (DataHeader*)szRecv;
		switch (header->cmd)
		{
		case CMD_LOGIN:
		{
			Login* _login;
			//读取Header->dataLength的数据长度  将数据继续读入saRecv这个块里面
			recv(_clientSock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
			_login = (Login*)szRecv;
			cout << "收到命令:CMD_LOGIN" << " 数据长度 = " << header->dataLength << " UserName = " << _login->userName << " Password = " << _login->Password << endl;
			//忽略了判断用户名密码是否正确的过程
			LoginResult _loginres;
			_loginres.result = 200;
			send(_clientSock, (char*)&_loginres, sizeof(LoginResult), 0);
		}break;
		case CMD_LOGINOUT:
		{
			Logout* _logout;
			recv(_clientSock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
			_logout = (Logout*)szRecv;
			cout << "收到命令:CMD_LOGOUT" << " 数据长度 = " << header->dataLength << " UserName = " << _logout->userName << endl;
			LogoutResult _logoutres;
			_logoutres.result = 200;
			send(_clientSock, (char*)&_logoutres, sizeof(LogoutResult), 0);
		}break;
		default:
		{
			header->cmd = CMD_ERROR;
			header->dataLength = 0;
			send(_clientSock, (char*)&header, sizeof(DataHeader), 0);
		}
		break;
		}
	}


	//	6. 关闭socket
	closesocket(_sock);
	// 清除Windows socket环境
	WSACleanup();
	return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/927974.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-17
下一篇 2022-05-17

发表评论

登录后才能评论

评论列表(0条)

保存