码迷,mamicode.com
首页 > Windows程序 > 详细

解决WinSock中发送、接收多包问题

时间:2015-02-23 15:26:02      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

最近在写自己的开发库写到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<vector>
using namespace std;

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

char * RecvPacket(SOCKET RecvSock)
{
	vector<char *> 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;
}

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

解决WinSock中发送、接收多包问题

标签:

原文地址:http://www.cnblogs.com/laijingwu/p/4298037.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!