socket编程 单向服务端与客户端通信之简单协议,仅供参考

4 篇文章 0 订阅
3 篇文章 0 订阅

Hello,大家好,这次写的socket网络编程 是关于服务端与客户端通信之简单协议的实现 , 当然这是应用层的协议 。

很简单,具体的通信过程是 客户端给服务端传送( 操作数个数 操作数 和 操作符),而服务端接收到数据后,进行解析并计算,最后将计算结果发送给客户端,这只能是很多复杂协议的最简单版本了,主要是通过简单来看透复杂的东西,将复杂看简单。Talk is cheap , show me the code.


server.c

#include<stdlib.h>
#include<stdio.h>
#include<WinSock2.h>
#define BUF_SIZE 1024
#pragma comment(lib,"ws2_32.lib")
int main(){
	WSADATA wsd;
	SOCKET sServer, sClient;
	SOCKADDR_IN addrServer, addrClient;
	int recvCount = 100;
	int sizeAddrClient = 0;
	char sendBuf[BUF_SIZE];
	char recvBuf[BUF_SIZE];
	int opMsg[1024] = {0};
	
	const int OPSZ = 4;
	//初始化socket库
	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0){
		ErrorHandling("WSAStartup error!");
	}
	puts("初始化socket库");

	//创建服务端socket
	sServer = socket(AF_INET, SOCK_STREAM, 0);
	if (sServer == INVALID_SOCKET){
		ErrorHandling("socket() error!");
	}
	puts("创建服务端socket");

	//初始化网络地址信息
	memset(&addrServer, 0, sizeof(addrServer));
	addrServer.sin_family = AF_INET;
	addrServer.sin_addr.S_un.S_addr = htonl(ADDR_ANY);
	addrServer.sin_port = htons(6000);
	puts("初始化网络地址信息");

	//绑定地址信息到服务端socket
	if (bind(sServer, (SOCKADDR*)&addrServer, sizeof(addrServer)) == SOCKET_ERROR){
		ErrorHandling("bind() error!");
	}
	puts("绑定地址信息到服务端socket");

	//服务端进行监听
	if (listen(sServer, 5) == SOCKET_ERROR){
		ErrorHandling("listen() error!");
	}
	puts("服务端进行监听ing");

	sizeAddrClient = sizeof(addrClient);
	//服务端进入接收消息状态(阻塞模式)
	sClient = accept(sServer, (SOCKADDR*)&addrClient, &sizeAddrClient);
	if (sClient == INVALID_SOCKET){
		ErrorHandling("accept() error!");
	}
	printf("有用户连接:%s\n", inet_ntoa(addrClient.sin_addr));
	char operator = '\0';
	//循环接收消息(我规定最多为200次)
	while (recvCount>0){
		memset(recvBuf, 0, BUF_SIZE);
		memset(recvBuf, 0, BUF_SIZE);
		int recvNum = recv(sClient, recvBuf, 1024, 0);
		if (recvNum == -1){
			printf("exit\n");
			break;
		}
		//获取操作数个数
		int opt_num = (char)recvBuf[0];
		//获取操作数,存入opMsg数组中
		int i = 0;
		for (i = 0; i < opt_num;i++){
			memcpy(&opMsg[i], &recvBuf[OPSZ * i + 1], OPSZ);
		}
		//获取操作符
		char operator = recvBuf[i*OPSZ + 1];
		printf("%c",operator);
		//根据操作符计算结果
		int results = 0;
		switch (operator){
			case '+':
				results = 0;
				for (i = 0; i < opt_num;i++){
					results += opMsg[i];
				}
				break;
			case '-':
				results = opMsg[0];
				for (i = 1; i < opt_num; i++){
					results -= opMsg[i];
				}
				break;
			case '*':
				results =1 ;
				for (i = 0; i < opt_num; i++){
					results *= opMsg[i];
				}
				break;
			default:
				ErrorHandling("错误的操作符!");
		}
		//将结果数据复制到charBuf前4个字节中,并发送给客户端
		memcpy(sendBuf, &results, OPSZ);
		send(sClient, sendBuf, OPSZ, 0);
		recvCount--;
	}
	//关闭socket
	closesocket(sClient);
	closesocket(sServer);
	WSACleanup();
	puts("关闭socket");
	system("pause");
	return 0;
}

client.c

#include<stdlib.h>
#include<stdio.h>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#define BUF_SIZE 1024
void ErrorHandling(char * msg){
	puts(msg);
	system("pause");
	exit(1);
}

int main2(){
	WSADATA wsd;
	SOCKET  sClient;
	SOCKADDR_IN addrClient;
	int sizeAddrClient = 0;
	int recvCount = 100;
	char charBuf[BUF_SIZE] = { 0 };
	const int OPSZ = 4;
	//初始化socket库
	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0){
		ErrorHandling("WSAStartup error!");
	}
	puts("初始化socket库");

	//创建客户端socket
	sClient = socket(AF_INET, SOCK_STREAM, 0);
	if (sClient == INVALID_SOCKET){
		ErrorHandling("socket() error!");
	}
	puts("创建客户端socket");

	//初始化网络地址信息
	memset(&addrClient, 0, sizeof(addrClient));
	addrClient.sin_family = AF_INET;
	addrClient.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrClient.sin_port = htons(6000);
	puts("初始化网络地址信息");

	//连接服务端
	if (connect(sClient, (SOCKADDR*)&addrClient, sizeof(addrClient)) == SOCKET_ERROR){
		ErrorHandling("connect error!");
	}
	puts("现在可以向服务端发送消息");
	
	int recvNum = 0;
	char charRecv[BUF_SIZE];
	char opMsg[BUF_SIZE];
	int i = 0;
	//循环发送消息(我规定最多为200次)
	while (recvCount>0){
		memset(opMsg, 0, BUF_SIZE);
		memset(charRecv, 0, 1024);
		//输入操作数的个数
		printf("输入操作数的个数:");
		int opt_num = 0;
		scanf("%d",&opt_num);
		//将输入的个数 存入第一个字节中,因为不需要太大
		opMsg[0] = (char)opt_num;
		//输入每一个操作数(注意类型转换)
		for (i = 0; i < opt_num; i++){
			printf("Operand %d:",i+1);
			scanf("%d", (int *)&opMsg[i*OPSZ+1]);
		}
		//清理一下标准输入 , 如果不清理,下面操作符就直接存入'回车'了。
		fflush(stdin);
		printf("Operator:");
		//输入操作符
		scanf("%c",&opMsg[i*OPSZ]+1);
		fflush(stdin);
		//将字符数组发送至服务端
		/*
			这里有必要说一下服务端与客户端传输的数据格式
			第一个字节:操作数的个数
			第2-5 字节:第一个操作数
			第6-9 字节:第二个操作数
			以此类推
			最后一个操作数的下一个字节(也就是格式中的最后一个字节):操作符(*,+,-)
		*/
		//opt_num*OPSZ+2 也就是操作数个数*每个操作数所占字节数+一个操作数个数+一个操作符
		int sendLen = send(sClient, opMsg, opt_num*OPSZ + 2, 0);
		//发送完成之后,就接收计算结果了 4个字节的整数,放到charRecv中
		recv(sClient, charRecv, OPSZ, 0);
		int results = 0;
		//将charRecv 前4个字节的数据 复制到 results中
		memcpy(&results, charRecv, OPSZ);
		printf("results:%d\n", results);
		recvCount--;
	}
	//关闭socket
	closesocket(sClient);
	WSACleanup();
	puts("关闭socket");
	system("pause");
	return 0;
}

注释很完整了,如有不明白之处,请回复。

之后我会继续为大家带来简单易懂的socket程序。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值