使用WINSOCK的网络通信模拟程序(服务器端)

使用WINSOCK的网络通信模拟程序

(服务器端)

最近在做嵌入式的project过程中,学习了winsock网络编程,project主要的内容是在移植到stm32之前通过c语言对整个过程进行模拟;过程包括:一台client端的设备和一台作为服务器端的sensor设备通过TCP协议进行连接,通过client端输入不同指令对sensor端进行控制:
例如start命令唤醒sensor;
唤醒后输入任意指令获得sensor端返回的温度数值(此处为随机数生成);
唤醒后输入quit退出连接,结束模拟过程。

下面是一些说明:
1.sensor端作为服务器,代码分为通讯模块、控制模块、温度模块。
2.考虑到TCP协议通过三次握手进行连接,有助于保证sensor端和client端通信的稳定性,我们使用TCP通信替代了推荐的UDP通信,因此代码部分中大规模的代码是通讯模块。
3.控制模块是对client端的信息进行鉴别(实际上就是设置不同信号的相应优先级,因为project比较简单,此处只设置了三级响应)
4.温度模块在此代码中只是通过随机数生成的35.0-42.9之间的数值,在单片机开发板版本中为通过温度传感器检测到的实际数值。

补充:project的完整源码已经update到gitee,后续的改进将逐步进行,大家感兴趣的话可以看看gitee连接

此处鸣谢一起完成project的负责单片机部分的王同学CSDN个人空间,负责GUI部分的张同学和司马同学

此处为客户机部分文章链接https://blog.csdn.net/capodexi/article/details/106802557
此部分为sensor端源码

#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include<WINSOCK2.h>
#include<string.h>
#include<iostream>
#include<tchar.h>
#pragma comment(lib,"WS2_32.lib")
#define BUF_SIZE 64
//设置头文件,库文件与常量(缓冲区大小)

int _tmain(int argc, _TCHAR* argv[])
{
	WSADATA wsd;
	SOCKET sServer;
	SOCKET sClient;
	SOCKADDR_IN servAddr;
	char buf[BUF_SIZE];
	int retVal;
	//声明程序所需的变量

	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
	{
		printf("WSAStartup failed! \n");
		return 1;
	}
	//初始化Socket环境

	sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sServer)
	{
		printf("socket failed! \n");
		WSACleanup();
		return -1;
	}
	//创建server端的Socket

	SOCKADDR_IN addrServ;
	addrServ.sin_family = AF_INET;
	addrServ.sin_port = htons(9990);
	addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	//设置服务器监听地址为任意本地地址,设置端口号为9990

	retVal = bind(sServer, (const struct sockaddr*)&addrServ, sizeof(SOCKADDR_IN));
	if (retVal == SOCKET_ERROR)
	{
		printf("bind failed!\n");
		closesocket(sServer);
		WSACleanup();
		return -1;
	}
	//绑定SocketServer到本地地址

	retVal = listen(sServer, 1);
	if (SOCKET_ERROR == retVal)
	{
		printf("listen failed! \n");
		closesocket(sServer);
		WSACleanup();
		return -1;
	}
	//在ServerSocket上进行监听

	printf("TCP server socket start...\n");
	sockaddr_in addrClient;
	int addrClientlen = sizeof(addrClient);
	sClient = accept(sServer, (sockaddr FAR*) & addrClient, &addrClientlen);
	if (sClient == INVALID_SOCKET)
	{
		printf("accept error!\n ");
		closesocket(sServer);
		WSACleanup();
		return -1;
	}
	//接受客户端请求

	int j = 0;
	printf("TCP server syart successfully!\n");
	while (true)
	{
		ZeroMemory(buf, BUF_SIZE);
		retVal = recv(sClient, buf, BUFSIZ, 0);
		if (SOCKET_ERROR == retVal)
		{
			printf("recv failed! \n");
			closesocket(sServer);
			closesocket(sClient);
			WSACleanup();
			return -1;
		}
		if (strcmp(buf, "start") != 0 && j == 0)
		{
			char cls[BUF_SIZE] = "sensor has not worked yet!Please press 'start'!\n ";
			strcpy(buf, cls);
			retVal = send(sClient, buf, strlen(buf), 0);
			if (SOCKET_ERROR == retVal)
			{
				printf("send failed! \n");
				closesocket(sServer);
				closesocket(sClient);
				WSACleanup();
				return -1;
			}
			j++;
			continue;
		}//sensor端启动命令检测
		if (strcmp(buf, "start") == 0||j == 0)
		{
			char sta[BUF_SIZE] = "sensor start!";
			printf("service start!");
			strcpy(buf, sta);
			retVal = send(sClient,buf, strlen(buf), 0);
			if (SOCKET_ERROR == retVal)
			{
				printf("send failed! \n");
				closesocket(sServer);
				closesocket(sClient);
				WSACleanup();
				return -1;
			}
			j++;
			continue;
		}//相应启动命令的输出信息
		
		if (strcmp(buf, "quit") == 0)
		{
			retVal = send(sClient, "quit", strlen("quit"), 0);
			printf("Shutdown command recieved!");
			break;
		}//exit 
		int p,q,r;
		char msg[BUF_SIZE];
		memset(msg, 0, sizeof(msg));
		p = rand() % 2 + 3;
		if (p==3)
		{
			q = rand() % 5 + 5;
		}
		else
		{
			q = rand() % 3 + 0;
		}
		r = rand() % 10 + 0;
		srand((unsigned)time(NULL));
		msg[0]=(char)'0'+p;
		msg[1]=(char)'0'+q;
		msg[2]=46;
		msg[3]=(char)'0'+r;
		msg[4]='\0';
		//生成随机数,范围35.0-42.0
		SYSTEMTIME st;
		GetLocalTime(&st);
		printf("%4d-%2d-%2d  %2d:%2d:%2d, Recv From Client [%s:%d]:%s\n",
			st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
			inet_ntoa(addrClient.sin_addr), addrClient.sin_port, "Temprature Sending Now");
		
		if(j>=0)
		{
			retVal = send(sClient,msg, strlen(msg), 0);
			if (SOCKET_ERROR == retVal)
			{
				printf("send failed! \n");
				closesocket(sServer);
				closesocket(sClient);
				WSACleanup();
				return -1;
			}
		}


	}
	//服务器与客户端传送信息

	closesocket(sServer);
	closesocket(sClient);
	WSACleanup();
	//释放空间
	system("pause");
	return 0;



	system("pause");
	return 0;
}

制作不易,感谢您的支持!

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TCP(Transmission Control Protocol)是Internet协议族中的一种传输层协议,用于在不可靠的网络环境中提供可靠的、基于字节流的通信服务。在Windows系统中,使用Winsock API进行TCP异步通信的控制台程序涉及以下几个关键步骤: 1. **初始化Winsock库**: 首先,你需要包含Winsock头文件,并调用`WSADATA wsaData;` 初始化结构和`WSAStartup()` 函数,以启动Winsock服务。 ```cpp #include <winsock2.h> #include <ws2tcpip.h> WSADATA wsaData; int result = WSAStartup(MAKEWORD(2, 2), &wsaData); if (result != 0) { // 处理错误,通常打印错误代码 } ``` 2. **定义套接字**: 使用`socket()`函数创建一个套接字,指定AF_INET(IPv4)和SOCK_STREAM(TCP流式)类型。 ```cpp SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { // 处理错误 } ``` 3. **设置服务器地址**: 对于客户程序,这通常是获取远程服务器的地址;对于服务器程序,则需要设置监听地址。 4. **连接或接受连接**: 对于客户使用`connect()`连接到服务器服务器则需要调用`bind()`和`listen()`后,使用`accept()`接收连接。 5. **发送和接收数据**: 使用`send()`发送数据,`recv()`接收数据。异步操作通常通过提供回调函数来处理完成事件,而不是阻塞主线程。 6. **错误处理**: 在整个通信过程中,要检查返回值并处理可能出现的错误,如`WSAGetLastError()`。 7. **关闭连接和清理**: 一旦通信完成,调用`shutdown()`关闭套接字的部分或全部连接,然后使用`closesocket()`关闭套接字,最后调用`WSACleanup()`结束Winsock

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值