博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解决WinSock中发送、接收多包问题
阅读量:6442 次
发布时间:2019-06-23

本文共 2231 字,大约阅读时间需要 7 分钟。

最近在写自己的开发库写到Socket时遇到一个很头疼的问题,那就是在发送时发送内容可能会比缓冲区大,而在接收时又不好判断什么时候接收完数据。所以写了一种发送时分割发送和分包接收后拼接的解决方案。而接收时判断数据是否传输结束,我用了select。这里以阻塞式为例子。

首先,我们需要定义一个常量,那就是我们分包时每个包的大小。如下:

#define EACH_PACK_SIZE 1024	// 单个数据包大小

在发送时,我采用了分割字符串进行分包发送的方法发送数据。

bool SendPacket(SOCKET SendSock, const char * pContent){	unsigned int unPackSum = strlen(pContent) / EACH_PACK_SIZE;	// 计算分包数量	if (strlen(pContent) % EACH_PACK_SIZE != 0)		unPackSum += 1;	char **szSendPack = (char **)calloc(unPackSum, sizeof(char));	// 分配内存用以存放分包内容		for (size_t i = 0; i < unPackSum; i++)	{		szSendPack[i] = (char *)calloc(EACH_PACK_SIZE + 1, sizeof(char));	// 分配内存给每个分包		strncpy_s(szSendPack[i], EACH_PACK_SIZE + 1, pContent + i * EACH_PACK_SIZE, EACH_PACK_SIZE);	// 读入分包至数组	}	for (size_t i = 0; i < unPackSum; i++)	{		ErrorCode = send(SendSock, szSendPack[i], strlen(szSendPack[i]), 0);	// 发送数据包		if (ErrorCode == SOCKET_ERROR)	// 发送失败		{			closesocket(SendSock);			return false;		}	}	for (size_t i = 0; i < unPackSum; i++)	// 释放内存		free(szSendPack[i]);	return true;}

而对于接收数据,由于接收数据长度不定,因此用char二维数组是不方便的,因此我选择了vector来做容器。因此,在使用前应当引用:

#include
using namespace std;

引用后,我们就可以这样处理接收数据了。

char * RecvPacket(SOCKET RecvSock){	vector
vecRecvPack; // 存放接收分包 bool bEmptyPack = false; fd_set crfd; timeval td = { 5, 0 }; while (true) { FD_ZERO(&crfd); FD_SET(RecvSock, &crfd); select(0, &crfd, NULL, NULL, &td); if (FD_ISSET(RecvSock, &crfd)) { bEmptyPack = false; char *szRecvTmp = (char *)calloc(EACH_PACK_SIZE + 1, sizeof(char)); // 分配内存用以缓冲分包 ErrorCode = recv(RecvSock, szRecvTmp, EACH_PACK_SIZE, 0); vecRecvPack.push_back(szRecvTmp); // 放入分包至数组 FD_ZERO(&crfd); td = { 0, 0 }; FD_SET(RecvSock, &crfd); select(0, &crfd, NULL, NULL, &td); if (FD_ISSET(RecvSock, &crfd)) continue; else break; } else { bEmptyPack = true; } } if (bEmptyPack){ //空数据包丢弃连接 return char(); } char *szRecvPack = (char *)calloc(EACH_PACK_SIZE * vecRecvPack.size() + 1, sizeof(char)); // 合成分包 for (size_t i = 0; i < vecRecvPack.size(); i++) { strncpy_s(szRecvPack + (i * EACH_PACK_SIZE), EACH_PACK_SIZE + 1, vecRecvPack[i], EACH_PACK_SIZE); // 读入分包内容至字符串 } return szRecvPack;}

至此,分包发送和接收就完成了。

转载于:https://www.cnblogs.com/laijingwu/p/4298037.html

你可能感兴趣的文章
另类的图表标签
查看>>
PHP连接MSSQL数据库案例,PHPWAMP多个PHP版本连接SQL Server数据库
查看>>
执行media-relay时报ImportError: No module named application
查看>>
我的友情链接
查看>>
深入理解计算机系统-第三章阅读笔记
查看>>
vmware配置经验记录
查看>>
06、林信任快捷方式
查看>>
[Vim]以sudo权限来保存vim打开的readonly文件
查看>>
zencart 如何调用边框等
查看>>
利用飞信自动发短信脚本
查看>>
vSphere 6.5试用
查看>>
使用Oracle外部表分析访问日志
查看>>
ajax 加载页面
查看>>
贪吃蛇游戏
查看>>
使用IBM WCM配置信息发布的操作步骤(上篇)
查看>>
centos安装后简单配置
查看>>
MPLS 2个转发平面
查看>>
mysql索引原理及联合应用小记
查看>>
NSObject 对象的真正架构
查看>>
学习笔记-Redis设计与实现-简单动态对象(simple dynamic string, SDS)
查看>>