通过网络发送数据,服务端增加缓冲区后,收发数据包量异常

色郎中 2020-04-09 10:46:50
服务端发送数据初始代码:
	//发送数据		
int SendData(DataHeader* header)
{
if (header)
{
return send(_sockfd, (const char*)header, header->dataLength, 0);
}
return SOCKET_ERROR;
//}




服务器端发送增加缓冲区后的代码:

收发测试,客户和服务两端数据量都非常非常小。 换回原来的SendData(上面的就3行代码),其他地方啥都没改动,收发测试两端数量非常大,这才正常。

是什么个情况呢?
vs2019+ WIN10家庭版,本地测试。

是网络环境问题 还是系统问题,还是其他问题?

 //发送数据
int SendData( DataHeader* header)
{
int ret = SOCKET_ERROR;
//要发生的数据长度
int nSendLen = header->dataLength;
//要发送的数据
const char* pSendData = (const char*)header;
while (true)
{
if (_lastSendPos + nSendLen >= SEND_BUFF_SIZE)
{
// 计算可以拷贝的数据长度
int nCopyLen = SEND_BUFF_SIZE - _lastSendPos;
//拷贝数据
memcpy(_szSendBuf + _lastSendPos, pSendData, nCopyLen);
//计算剩余数据位置
pSendData += nCopyLen;
//计算剩余数据长度
nSendLen -= nSendLen;
ret = send(_sockfd, _szSendBuf, SEND_BUFF_SIZE, 0);
//数据尾部置为0
_lastSendPos = 0;
//如果发送错误,比如网络断开,客户端断开
if (SOCKET_ERROR==ret)
{
return ret;
}
}else
{
//将要发送的数据拷贝到发送缓冲区的尾部
memcpy(_szSendBuf + _lastSendPos, pSendData, nSendLen);
//计算数据尾部位置
_lastSendPos += nSendLen;
break;//当要发送的数据大于缓冲区时,循环发送,小于时跳出循环
}
}
return ret;
}
...全文
134 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
莫失莫忘218 2020-10-27
  • 打赏
  • 举报
回复
yukint 2020-04-09
  • 打赏
  • 举报
回复
nSendLen -= nSendLen; //变成0了 _lastSendPos = 0; 所以只要执行一次, if (_lastSendPos + nSendLen >= SEND_BUFF_SIZE)这个条件就无法满足了 只能发一次; // 再来说前面的代码为何OK,这里假设你写的是流套接字_sockfd,默认情况下的写是阻塞的, 也就是说内核缓冲区如果满的话,你的函数就阻塞了,进程被暂时挂起,当内核缓冲区有空间可以容纳 你所要发送的数据时,你的进程得以继续执行,也就是继续write。 ~~~~~你写的第二种情况时主要是针对非阻塞模式时做的,你没必要再弄一个_szSendBuf 来暂存他 而且你的逻辑写得太复杂了,导致很容易出错, 可以参考网络编程

 //发送数据
	int SendData( DataHeader* header)
	{
		int ret = SOCKET_ERROR;
		//要发生的数据长度
        int nleft = header->dataLength;
        const char *sendptr = (char *)header;

		while (nleft > 0)
		{
                //只管把剩余的一起发了,就算是非阻塞的,系统发送不完也没关系的
                //通过ret告知你,此次send成功发送了多少
				ret = send(_sockfd, sendptr, nleft, 0);
				if (SOCKET_ERROR==ret)
				{
					return ret;
				}
                else{
                    nleft -= ret;
                    sendptr += ret;
                }
		}		
		return nleft;   //返回成功写了多少
	}
色郎中 2020-04-09
  • 打赏
  • 举报
回复
感谢回复,代码没有问题,逻辑也没问题 可能是网络环境或系统的问题? 总之,工程一行代码没改,放到Linux下跑正常,,,回来再到win下跑正常。期间就重启过win10系统,启动了个虚拟机 很邪门
引用 1 楼 yukint 的回复:
nSendLen -= nSendLen; //变成0了 _lastSendPos = 0; 所以只要执行一次, if (_lastSendPos + nSendLen >= SEND_BUFF_SIZE)这个条件就无法满足了 只能发一次; // 再来说前面的代码为何OK,这里假设你写的是流套接字_sockfd,默认情况下的写是阻塞的, 也就是说内核缓冲区如果满的话,你的函数就阻塞了,进程被暂时挂起,当内核缓冲区有空间可以容纳 你所要发送的数据时,你的进程得以继续执行,也就是继续write。 ~~~~~你写的第二种情况时主要是针对非阻塞模式时做的,你没必要再弄一个_szSendBuf 来暂存他 而且你的逻辑写得太复杂了,导致很容易出错, 可以参考网络编程

 //发送数据
	int SendData( DataHeader* header)
	{
		int ret = SOCKET_ERROR;
		//要发生的数据长度
        int nleft = header->dataLength;
        const char *sendptr = (char *)header;

		while (nleft > 0)
		{
                //只管把剩余的一起发了,就算是非阻塞的,系统发送不完也没关系的
                //通过ret告知你,此次send成功发送了多少
				ret = send(_sockfd, sendptr, nleft, 0);
				if (SOCKET_ERROR==ret)
				{
					return ret;
				}
                else{
                    nleft -= ret;
                    sendptr += ret;
                }
		}		
		return nleft;   //返回成功写了多少
	}

64,281

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧