socket 频繁send会导致数据丢失? (C++)

小乌龟在大乌龟背上 2017-07-13 01:29:55
一旦send后 加上一个sleep,就不会出现问题,这个是什么情况~
会不会是没有及时把缓冲区的内容取走?
...全文
784 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2017-07-21
  • 打赏
  • 举报
回复
任何收发两端速度不一致的通讯,都需要在它们之间使用一个足够大的FIFO缓冲区。 对任何FIFO缓冲区的使用,都需要仔细考虑接收端接收时超时无数据和发送端发送时FIFO缓冲区已满这两种情况下该如何做。
jklinux 2017-07-14
  • 打赏
  • 举报
回复
引用 8 楼 what951006 的回复:
[quote=引用 7 楼 jklinux 的回复:] 我遇到过同样的问题。 解决办法: 在接收端专用一个线程来接收数据,数据的缓冲区需要8K以上,接收数据后加入数据队列。 在数据队列里的数据再用另一线程来专门处理。 当然如果数据量不大的话,用应答机制也可以。 即发送端发出数据, 另一端接收数据后回个应答, 发送端接收到应答后再发出数据....
我解决了,我把接收端与发送端的缓冲区都设置为了1MB,就解决了,应该和我最开始的猜测有关。。缓冲区没来得及读,后面的数据就丢失了[/quote] 确实,最主要你还有数据处理了,不处理应也不会丢
kakabulusi 2017-07-14
  • 打赏
  • 举报
回复
粘包和滑动窗口 是流式套接字传输数据必然要遇到的问题,解决方法也有很多
  • 打赏
  • 举报
回复
引用 7 楼 jklinux 的回复:
我遇到过同样的问题。 解决办法: 在接收端专用一个线程来接收数据,数据的缓冲区需要8K以上,接收数据后加入数据队列。 在数据队列里的数据再用另一线程来专门处理。 当然如果数据量不大的话,用应答机制也可以。 即发送端发出数据, 另一端接收数据后回个应答, 发送端接收到应答后再发出数据....
我解决了,我把接收端与发送端的缓冲区都设置为了1MB,就解决了,应该和我最开始的猜测有关。。缓冲区没来得及读,后面的数据就丢失了
jklinux 2017-07-14
  • 打赏
  • 举报
回复
我遇到过同样的问题。 解决办法: 在接收端专用一个线程来接收数据,数据的缓冲区需要8K以上,接收数据后加入数据队列。 在数据队列里的数据再用另一线程来专门处理。 当然如果数据量不大的话,用应答机制也可以。 即发送端发出数据, 另一端接收数据后回个应答, 发送端接收到应答后再发出数据....
ID870177103 2017-07-14
  • 打赏
  • 举报
回复
TCP有自带的流量控制协议,叫滑动窗口 所以问题可能是你CS端sendall和recvall的size不一样
ztenv 版主 2017-07-14
  • 打赏
  • 举报
回复
引用 13 楼 what951006 的回复:
[quote=引用 11 楼 lianshaohua 的回复:] [quote=引用 8 楼 what951006 的回复:] [quote=引用 7 楼 jklinux 的回复:] 我遇到过同样的问题。 解决办法: 在接收端专用一个线程来接收数据,数据的缓冲区需要8K以上,接收数据后加入数据队列。 在数据队列里的数据再用另一线程来专门处理。 当然如果数据量不大的话,用应答机制也可以。 即发送端发出数据, 另一端接收数据后回个应答, 发送端接收到应答后再发出数据....
我解决了,我把接收端与发送端的缓冲区都设置为了1MB,就解决了,应该和我最开始的猜测有关。。缓冲区没来得及读,后面的数据就丢失了[/quote] 可以明确的告诉你,不是你猜测的原因。如果不相信,可以做一个实验:把缓冲区设置为1kB,然后你把每次接收的数据都打印到控制台或写到文件中,可以测试一下接收的与发送的是不是一致的。[/quote] 版主英明,才发现是我的recvAll写错了,而把缓冲区改大了只是刚刚好一次就发送过去了,接收也只执行了一次循环~!所以还是版主英明[/quote] 前面已经提示过你了,你发现错误了就好;总之和缓冲区大小没有任何关系。
  • 打赏
  • 举报
回复
引用 11 楼 lianshaohua 的回复:
[quote=引用 8 楼 what951006 的回复:] [quote=引用 7 楼 jklinux 的回复:] 我遇到过同样的问题。 解决办法: 在接收端专用一个线程来接收数据,数据的缓冲区需要8K以上,接收数据后加入数据队列。 在数据队列里的数据再用另一线程来专门处理。 当然如果数据量不大的话,用应答机制也可以。 即发送端发出数据, 另一端接收数据后回个应答, 发送端接收到应答后再发出数据....
我解决了,我把接收端与发送端的缓冲区都设置为了1MB,就解决了,应该和我最开始的猜测有关。。缓冲区没来得及读,后面的数据就丢失了[/quote] 可以明确的告诉你,不是你猜测的原因。如果不相信,可以做一个实验:把缓冲区设置为1kB,然后你把每次接收的数据都打印到控制台或写到文件中,可以测试一下接收的与发送的是不是一致的。[/quote] 版主英明,才发现是我的recvAll写错了,而把缓冲区改大了只是刚刚好一次就发送过去了,接收也只执行了一次循环~!所以还是版主英明
  • 打赏
  • 举报
回复
引用 11 楼 lianshaohua 的回复:
[quote=引用 8 楼 what951006 的回复:] [quote=引用 7 楼 jklinux 的回复:] 我遇到过同样的问题。 解决办法: 在接收端专用一个线程来接收数据,数据的缓冲区需要8K以上,接收数据后加入数据队列。 在数据队列里的数据再用另一线程来专门处理。 当然如果数据量不大的话,用应答机制也可以。 即发送端发出数据, 另一端接收数据后回个应答, 发送端接收到应答后再发出数据....
我解决了,我把接收端与发送端的缓冲区都设置为了1MB,就解决了,应该和我最开始的猜测有关。。缓冲区没来得及读,后面的数据就丢失了[/quote] 可以明确的告诉你,不是你猜测的原因。如果不相信,可以做一个实验:把缓冲区设置为1kB,然后你把每次接收的数据都打印到控制台或写到文件中,可以测试一下接收的与发送的是不是一致的。[/quote] 事实是改大后刚好能解决问题。。我测试一下
ztenv 版主 2017-07-14
  • 打赏
  • 举报
回复
引用 8 楼 what951006 的回复:
[quote=引用 7 楼 jklinux 的回复:] 我遇到过同样的问题。 解决办法: 在接收端专用一个线程来接收数据,数据的缓冲区需要8K以上,接收数据后加入数据队列。 在数据队列里的数据再用另一线程来专门处理。 当然如果数据量不大的话,用应答机制也可以。 即发送端发出数据, 另一端接收数据后回个应答, 发送端接收到应答后再发出数据....
我解决了,我把接收端与发送端的缓冲区都设置为了1MB,就解决了,应该和我最开始的猜测有关。。缓冲区没来得及读,后面的数据就丢失了[/quote] 可以明确的告诉你,不是你猜测的原因。如果不相信,可以做一个实验:把缓冲区设置为1kB,然后你把每次接收的数据都打印到控制台或写到文件中,可以测试一下接收的与发送的是不是一致的。
ztenv 版主 2017-07-13
  • 打赏
  • 举报
回复
引用 4 楼 what951006 的回复:
bool SendAll(SOCKET &sock, char*buffer, int size)
{
	int SendSize=0;
	while (size>0)//剩余部分大于0
	{
		SendSize = send(sock, buffer + SendSize, size, 0);
		if(SOCKET_ERROR==SendSize)
			return false;
		size = size - SendSize;
	}
	return true;
}

bool RecvAll(SOCKET &sock, char*buffer, int size)
{
	int RecvSize=0;
	while (size>0)//剩余部分大于0
	{
		RecvSize = recv(sock, buffer + RecvSize, size, 0);
		if(SOCKET_ERROR==RecvSize)
			return false;
		size = size - RecvSize;
	}
	return true;
}
这样的写法有没有什么不妥?
没有问题吗? send/recv都返回什么值?不止是SOCKET_ERROR吧?还有其他的错误,正常情况下返回的是发送/接收的长度。 看看send/recv的说明吧,windows:msdn;linux: man send
  • 打赏
  • 举报
回复
bool SendAll(SOCKET &sock, char*buffer, int size)
{
	int SendSize=0;
	while (size>0)//剩余部分大于0
	{
		SendSize = send(sock, buffer + SendSize, size, 0);
		if(SOCKET_ERROR==SendSize)
			return false;
		size = size - SendSize;
	}
	return true;
}

bool RecvAll(SOCKET &sock, char*buffer, int size)
{
	int RecvSize=0;
	while (size>0)//剩余部分大于0
	{
		RecvSize = recv(sock, buffer + RecvSize, size, 0);
		if(SOCKET_ERROR==RecvSize)
			return false;
		size = size - RecvSize;
	}
	return true;
}
这样的写法有没有什么不妥?
ztenv 版主 2017-07-13
  • 打赏
  • 举报
回复
1、tcp发送会有些滞后的,你发送成功了,并不代表数据已经到达对端了,tcp有一个延时打包发送的功能,可以禁用nagle算法, 2、接收的数据不完整,这有可能是tcp的分片导致的,建议你循环接收数据,直到收到你能够解析的数据为止,比如:你的包头500个字节的长度,如果第一次只收到100个字节,那么继续接收后续的400个字节,并与之前收到的拼包,直到接收完500个字节后,再解析
  • 打赏
  • 举报
回复
引用 楼主 what951006 的回复:
一旦send后 加上一个sleep,就不会出现问题,这个是什么情况~ 会不会是没有及时把缓冲区的内容取走?
TLV方式,你没理解我的意思。我的接收是单独的一个线程,首先接收包头,再根据包头的类型接收相应数据,问题不在这里,在send里面, send包头后,再循环send数据,在send数据里面,如果不加个sleep,接收的数据就不完整,是这样的一个问题。
qingdujun 2017-07-13
  • 打赏
  • 举报
回复
你是TCP通信吧?TCP通信是数据流,而不是一包一包到来的。其实数据已经来了,只是你没有拆开。 也就是N包,你当成一包数据读出来了。

65,184

社区成员

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

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