简单C/S模式1.2

简单C/S模式1.2

发送结构化的网络消息数据
在这里插入图片描述

一、数据格式定义,先发数据头,再发数据

server

#include <stdio.h>
#include <WinSock2.h>

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

//DataPackage

enum CMD{
	CMD_LOGIN,
	CMD_LOGOUT,
	CMD_ERROR
};

struct DataHeader{
	short cmd;			//命令
	short dataLength;	//数据长度
};

struct Login{
	char userName[32];
	char password[32];
};

struct LoginResult{
	int result;
};

struct Logout{
	char userName[32];
};

struct LogoutResult{
	int result;
};


int main(int argc, char* argvp[])
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	if (WSAStartup(sockVersion, &wsaData) != 0){
		return  -1;
	}

	//创建套接字
	SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == INVALID_SOCKET){
		printf("socket errot\n");
		WSACleanup();
		return -2;
	}

	//套接字结构体
	SOCKADDR_IN ser_addr;
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_port = htons(8888);
	ser_addr.sin_addr.S_un.S_addr = INADDR_ANY;	//inet_addr("127.0.0.1");

	//绑定IP和端口
	if (bind(sock, (struct sockaddr*)&ser_addr, sizeof(ser_addr)) == SOCKET_ERROR){
		printf("bind error\n");
		closesocket(sock);
		WSACleanup();
		return -3;
	}

	//监听端口
	if (listen(sock, 5) == SOCKET_ERROR){
		printf("listen error\n");
		closesocket(sock);
		WSACleanup();
		return -4;
	}

	//定义接收客户端的套接字
	SOCKET clientsock = INVALID_SOCKET;
	SOCKADDR_IN client_addr = {};
	int client_addr_len = sizeof(client_addr);
	//接受一个客户端连接
	clientsock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len);
	if (clientsock == INVALID_SOCKET){
		printf("accept error\n");
		closesocket(sock);
		WSACleanup();
		return -5;
	}
	printf("new client add, socket = %d, IP = %s\n",  clientsock, inet_ntoa(client_addr.sin_addr));

	while (true){
		DataHeader header = {};
		//接受客户端数据
		int nLen = recv(clientsock, (char*)&header, sizeof(DataHeader), 0);
		if (nLen < 0){
			printf("client exit.\n");
			break;
		}
		printf("recv cmd : %d, dataLength : %d\n", header.cmd, header.dataLength);
		switch (header.cmd){
		case CMD_LOGIN:
		{
			Login login = {};
			recv(clientsock, (char*)&login, sizeof(Login), 0);
			//用户名密码判断过程
			LoginResult ret = { 1 };
			send(clientsock, (const char*)&header, sizeof(DataHeader), 0);
			send(clientsock, (const char*)&ret, sizeof(LoginResult), 0);
		}
			break;
		case CMD_LOGOUT:
		{
			Logout logout = {};
			recv(clientsock, (char*)&logout, sizeof(Logout), 0);
			//用户名密码判断过程
			LogoutResult ret = { 1 };
			send(clientsock, (const char*)&header, sizeof(DataHeader), 0);
			send(clientsock, (const char*)&ret, sizeof(LogoutResult), 0);
		}
			break;
		default:
		{
			header.cmd = CMD_ERROR;
			header.dataLength = 0;
			send(clientsock, (const char*)&header, sizeof(DataHeader), 0);
		}
			break;
		}
	}
	//关闭套接字
	closesocket(sock);

	//清除window socket环境
	WSACleanup();
	getchar();
	return 0;
}

client

#include <stdio.h>
#include <WinSock2.h>

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

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

enum CMD{
	CMD_LOGIN,
	CMD_LOGOUT,
	CMD_ERROR
};

struct DataHeader{
	short cmd;			//命令
	short dataLength;	//数据长度
};

struct Login{
	char userName[32];
	char password[32];
};

struct LoginResult{
	int result;
};

struct Logout{
	char userName[32];
};

struct LogoutResult{
	int result;
};

int main(int argc, char* argvp[])
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;

	//启动window socket2.0环境
	if (WSAStartup(sockVersion, &wsaData) != 0){
		return  -1;
	}

	//创建socket
	SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == INVALID_SOCKET){
		printf("socket error\n");;
		WSACleanup();
		return -1;
	}

	//连接服务器
	sockaddr_in _sin = {};
	_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(8888);
	if (SOCKET_ERROR == connect(sock, (struct sockaddr*)&_sin, sizeof(_sin))){
		printf("connect error \n");
		closesocket(sock);
		WSACleanup();
		return -2;
	}

	//与服务器交互信息
	char cmdBuf[128] = {};
	while (true){
		//向服务器发送
		printf("input cmd : ");
		memset(cmdBuf, 0, sizeof(cmdBuf));
		scanf("%s", cmdBuf);
		
		if (0 == strcmp(cmdBuf, "exit")){
			printf("exit\n");
			break;
		}
		else if (0 == strcmp(cmdBuf, "login")){
			Login login = { "admin", "admin123" };
			DataHeader dh = { CMD_LOGIN, sizeof(Login) };
			send(sock, (const char*)&dh, sizeof(DataHeader), 0);
			send(sock, (const char*)&login, sizeof(Login), 0);

			DataHeader retHeader = {};
			LoginResult loginRet = {};
			recv(sock, (char*)&retHeader, sizeof(DataHeader), 0);
			recv(sock, (char*)&loginRet, sizeof(LoginResult), 0);
			printf("loginRet : %d\n", loginRet.result);
		}
		else if (0 == strcmp(cmdBuf, "logout")){
			Logout logout = { "admin" };
			DataHeader dh = { CMD_LOGOUT, sizeof(Logout) };
			send(sock, (const char*)&dh, sizeof(DataHeader), 0);
			send(sock, (const char*)&logout, sizeof(Logout), 0);

			DataHeader retHeader = {};
			LogoutResult logoutRet = {};
			recv(sock, (char*)&retHeader, sizeof(DataHeader), 0);
			recv(sock, (char*)&logoutRet, sizeof(LogoutResult), 0);
			printf("logoutRet : %d\n", logoutRet.result);
		}
		else{
			printf("Cmd no support, please input again.\n");
		}

	}
	//关闭套接字
	closesocket(sock);

	//清除window socket环境
	WSACleanup();
	getchar();
	return 0;
}

二、合并数据头和数据为一体

server

#include <stdio.h>
#include <WinSock2.h>

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

//DataPackage

enum CMD{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};

struct DataHeader{
	short cmd;			//命令
	short dataLength;	//数据长度
};

struct Login : public DataHeader{
	Login(){
		this->cmd = CMD_LOGIN;
		this->dataLength = sizeof(Login);
	}
	char userName[32];
	char password[32];
};

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

struct Logout : public DataHeader{
	Logout(){
		this->cmd = CMD_LOGIN;
		this->dataLength = sizeof(Logout);
	}
	char userName[32];
};

struct LogoutResult : public DataHeader{
	LogoutResult(){
		this->cmd = CMD_LOGOUT_RESULT;
		this->dataLength = sizeof(LogoutResult);
		result = 0;
	}
	int result;
};


int main(int argc, char* argvp[])
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	if (WSAStartup(sockVersion, &wsaData) != 0){
		return  -1;
	}

	//创建套接字
	SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == INVALID_SOCKET){
		printf("socket errot\n");
		WSACleanup();
		return -2;
	}

	//套接字结构体
	SOCKADDR_IN ser_addr;
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_port = htons(8888);
	ser_addr.sin_addr.S_un.S_addr = INADDR_ANY;	//inet_addr("127.0.0.1");

	//绑定IP和端口
	if (bind(sock, (struct sockaddr*)&ser_addr, sizeof(ser_addr)) == SOCKET_ERROR){
		printf("bind error\n");
		closesocket(sock);
		WSACleanup();
		return -3;
	}

	//监听端口
	if (listen(sock, 5) == SOCKET_ERROR){
		printf("listen error\n");
		closesocket(sock);
		WSACleanup();
		return -4;
	}

	//定义接收客户端的套接字
	SOCKET clientsock = INVALID_SOCKET;
	SOCKADDR_IN client_addr = {};
	int client_addr_len = sizeof(client_addr);
	//接受一个客户端连接
	clientsock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len);
	if (clientsock == INVALID_SOCKET){
		printf("accept error\n");
		closesocket(sock);
		WSACleanup();
		return -5;
	}
	printf("new client add, socket = %d, IP = %s\n",  clientsock, inet_ntoa(client_addr.sin_addr));

	while (true){
		DataHeader header = {};
		//接受客户端数据
		int nLen = recv(clientsock, (char*)&header, sizeof(DataHeader), 0);
		if (nLen <= 0){
			printf("client exit.\n");
			break;
		}
		
		switch (header.cmd){
		case CMD_LOGIN:
		{
			Login login = {};
			printf("address : %d\n", &login);
			recv(clientsock, (char*)&login + sizeof(DataHeader), sizeof(Login) - sizeof(DataHeader), 0);
			printf("recv cmd : CMD_LOGIN, dataLength : %d, userName=%s, password=%s\n", login.dataLength, login.userName, login.password);
			//用户名密码判断过程
			LoginResult ret;
			send(clientsock, (const char*)&ret, sizeof(LoginResult), 0);
		}
			break;
		case CMD_LOGOUT:
		{
			Logout logout = {};
			recv(clientsock, (char*)&logout + sizeof(DataHeader), sizeof(Logout) - sizeof(DataHeader), 0);
			printf("recv cmd : CMD_LOGOUT, dataLength : %d, userName=%s\n", logout.dataLength, logout.userName);
			//用户名密码判断过程
			LogoutResult ret;
			send(clientsock, (const char*)&ret, sizeof(LogoutResult), 0);
		}
			break;
		default:
		{
			header.cmd = CMD_ERROR;
			header.dataLength = 0;
			send(clientsock, (const char*)&header, sizeof(DataHeader), 0);
		}
			break;
		}
	}
	//关闭套接字
	closesocket(sock);

	//清除window socket环境
	WSACleanup();
	getchar();
	return 0;
}

client

#include <stdio.h>
#include <WinSock2.h>

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

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

enum CMD{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};

struct DataHeader{
	short cmd;			//命令
	short dataLength;	//数据长度
};

struct Login : public DataHeader{
	Login(){
		this->cmd = CMD_LOGIN;
		this->dataLength = sizeof(Login);
	}
	char userName[32];
	char password[32];
};

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

struct Logout : public DataHeader{
	Logout(){
		this->cmd = CMD_LOGOUT;
		this->dataLength = sizeof(Logout);
	}
	char userName[32];
};

struct LogoutResult : public DataHeader{
	LogoutResult(){
		this->cmd = CMD_LOGOUT_RESULT;
		this->dataLength = sizeof(LogoutResult);
		result = 0;
	}
	int result;
};

int main(int argc, char* argvp[])
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;

	//启动window socket2.0环境
	if (WSAStartup(sockVersion, &wsaData) != 0){
		return  -1;
	}

	//创建socket
	SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == INVALID_SOCKET){
		printf("socket error\n");;
		WSACleanup();
		return -1;
	}

	//连接服务器
	sockaddr_in _sin = {};
	_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(8888);
	if (SOCKET_ERROR == connect(sock, (struct sockaddr*)&_sin, sizeof(_sin))){
		printf("connect error \n");
		closesocket(sock);
		WSACleanup();
		return -2;
	}

	//与服务器交互信息
	char cmdBuf[128] = {};
	while (true){
		//向服务器发送
		printf("input cmd : ");
		memset(cmdBuf, 0, sizeof(cmdBuf));
		scanf("%s", cmdBuf);
		
		if (0 == strcmp(cmdBuf, "exit")){
			printf("exit\n");
			break;
		}
		else if (0 == strcmp(cmdBuf, "login")){
			Login login;
			strcpy(login.userName, "admin");
			strcpy(login.password, "admin123");
			send(sock, (const char*)&login, sizeof(Login), 0);

			LoginResult loginRet = {};
			recv(sock, (char*)&loginRet, sizeof(LoginResult), 0);
			printf("loginRet : %d\n", loginRet.result);
		}
		else if (0 == strcmp(cmdBuf, "logout")){
			Logout logout;
			strcpy(logout.userName, "admin");
			send(sock, (const char*)&logout, sizeof(Logout), 0);

			LogoutResult logoutRet = {};
			recv(sock, (char*)&logoutRet, sizeof(LogoutResult), 0);
			printf("logoutRet : %d\n", logoutRet.result);
		}
		else{
			printf("Cmd no support, please input again.\n");
		}

	}
	//关闭套接字
	closesocket(sock);

	//清除window socket环境
	WSACleanup();
	getchar();
	return 0;
}

三、使用数据头的数据长度字段,缓冲区偏移

server

#include <stdio.h>
#include <WinSock2.h>

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

//DataPackage

enum CMD{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};

struct DataHeader{
	short cmd;			//命令
	short dataLength;	//数据长度
};

struct Login : public DataHeader{
	Login(){
		this->cmd = CMD_LOGIN;
		this->dataLength = sizeof(Login);
	}
	char userName[32];
	char password[32];
};

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

struct Logout : public DataHeader{
	Logout(){
		this->cmd = CMD_LOGIN;
		this->dataLength = sizeof(Logout);
	}
	char userName[32];
};

struct LogoutResult : public DataHeader{
	LogoutResult(){
		this->cmd = CMD_LOGOUT_RESULT;
		this->dataLength = sizeof(LogoutResult);
		result = 0;
	}
	int result;
};


int main(int argc, char* argvp[])
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	if (WSAStartup(sockVersion, &wsaData) != 0){
		return  -1;
	}

	//创建套接字
	SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == INVALID_SOCKET){
		printf("socket errot\n");
		WSACleanup();
		return -2;
	}

	//套接字结构体
	SOCKADDR_IN ser_addr;
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_port = htons(8888);
	ser_addr.sin_addr.S_un.S_addr = INADDR_ANY;	//inet_addr("127.0.0.1");

	//绑定IP和端口
	if (bind(sock, (struct sockaddr*)&ser_addr, sizeof(ser_addr)) == SOCKET_ERROR){
		printf("bind error\n");
		closesocket(sock);
		WSACleanup();
		return -3;
	}

	//监听端口
	if (listen(sock, 5) == SOCKET_ERROR){
		printf("listen error\n");
		closesocket(sock);
		WSACleanup();
		return -4;
	}

	//定义接收客户端的套接字
	SOCKET clientsock = INVALID_SOCKET;
	SOCKADDR_IN client_addr = {};
	int client_addr_len = sizeof(client_addr);
	//接受一个客户端连接
	clientsock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len);
	if (clientsock == INVALID_SOCKET){
		printf("accept error\n");
		closesocket(sock);
		WSACleanup();
		return -5;
	}
	printf("new client add, socket = %d, IP = %s\n",  clientsock, inet_ntoa(client_addr.sin_addr));

	while (true){
		char szRecv[1024] = {};
		//接受客户端数据
		int nLen = recv(clientsock, szRecv, sizeof(DataHeader), 0);
		DataHeader* header = (DataHeader*)szRecv;
		if (nLen <= 0){
			printf("client exit.\n");
			break;
		}

		switch (header->cmd){
		case CMD_LOGIN:
		{
			recv(clientsock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
			Login* login = (Login*)szRecv;
			printf("recv cmd : CMD_LOGIN, dataLength : %d, userName=%s, password=%s\n", login->dataLength, login->userName, login->password);
			//用户名密码判断过程
			LoginResult ret;
			send(clientsock, (const char*)&ret, sizeof(LoginResult), 0);
		}
			break;
		case CMD_LOGOUT:
		{
			recv(clientsock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
			Logout* logout = (Logout*)szRecv;
			printf("recv cmd : CMD_LOGOUT, dataLength : %d, userName=%s\n", logout->dataLength, logout->userName);
			//用户名密码判断过程
			LogoutResult ret;
			send(clientsock, (const char*)&ret, sizeof(LogoutResult), 0);
		}
			break;
		default:
		{
			DataHeader header = { CMD_ERROR, 0 };
			send(clientsock, (const char*)&header, sizeof(DataHeader), 0);
		}
			break;
		}
	}
	//关闭套接字
	closesocket(sock);

	//清除window socket环境
	WSACleanup();
	getchar();
	return 0;
}

client

#include <stdio.h>
#include <WinSock2.h>

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

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

enum CMD{
	CMD_LOGIN,
	CMD_LOGIN_RESULT,
	CMD_LOGOUT,
	CMD_LOGOUT_RESULT,
	CMD_ERROR
};

struct DataHeader{
	short cmd;			//命令
	short dataLength;	//数据长度
};

struct Login : public DataHeader{
	Login(){
		this->cmd = CMD_LOGIN;
		this->dataLength = sizeof(Login);
	}
	char userName[32];
	char password[32];
};

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

struct Logout : public DataHeader{
	Logout(){
		this->cmd = CMD_LOGOUT;
		this->dataLength = sizeof(Logout);
	}
	char userName[32];
};

struct LogoutResult : public DataHeader{
	LogoutResult(){
		this->cmd = CMD_LOGOUT_RESULT;
		this->dataLength = sizeof(LogoutResult);
		result = 0;
	}
	int result;
};

int main(int argc, char* argvp[])
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;

	//启动window socket2.0环境
	if (WSAStartup(sockVersion, &wsaData) != 0){
		return  -1;
	}

	//创建socket
	SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == INVALID_SOCKET){
		printf("socket error\n");;
		WSACleanup();
		return -1;
	}

	//连接服务器
	sockaddr_in _sin = {};
	_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(8888);
	if (SOCKET_ERROR == connect(sock, (struct sockaddr*)&_sin, sizeof(_sin))){
		printf("connect error \n");
		closesocket(sock);
		WSACleanup();
		return -2;
	}

	//与服务器交互信息
	char cmdBuf[128] = {};
	while (true){
		//向服务器发送
		printf("input cmd : ");
		memset(cmdBuf, 0, sizeof(cmdBuf));
		scanf("%s", cmdBuf);
		
		if (0 == strcmp(cmdBuf, "exit")){
			printf("exit\n");
			break;
		}
		else if (0 == strcmp(cmdBuf, "login")){
			Login login;
			strcpy(login.userName, "admin");
			strcpy(login.password, "admin123");
			send(sock, (const char*)&login, sizeof(Login), 0);

			LoginResult loginRet = {};
			recv(sock, (char*)&loginRet, sizeof(LoginResult), 0);
			printf("loginRet : %d\n", loginRet.result);
		}
		else if (0 == strcmp(cmdBuf, "logout")){
			Logout logout;
			strcpy(logout.userName, "admin");
			send(sock, (const char*)&logout, sizeof(Logout), 0);

			LogoutResult logoutRet = {};
			recv(sock, (char*)&logoutRet, sizeof(LogoutResult), 0);
			printf("logoutRet : %d\n", logoutRet.result);
		}
		else{
			printf("Cmd no support, please input again.\n");
		}

	}
	//关闭套接字
	closesocket(sock);

	//清除window socket环境
	WSACleanup();
	getchar();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值