我又来了。。。Socket系统缓冲区不足或队列已满的问题

yangyangqinqin 2014-10-17 04:26:55
唉,最近用c# Socket写东西,碰到的问题太多了。。。

我在发送端发送一个比较大的内容(大概80M),接收端已经知道要接收内容的大小,因此用Receive函数循环接收直到所有数据接收完成:

int Offset = 0;
int Remain = PacketSize;
while (Remain > 0)
{
//int MinSize = Remain > 8192? 8192: Remain;
//int RealBytes = mClientSocket->Receive(mReceivePacketBuffer, Offset, MinSize , SocketFlags::None);

int RealBytes = mClientSocket->Receive(mReceivePacketBuffer, Offset, Remain, SocketFlags::None);

Offset += RealBytes;
Remain -= RealBytes;

Thread::Sleep(5);
}

如果循环中的Receive函数的Size参数尽量设置为最大,即将Size参数设置为没有接收完成的最大数量(程序中的 Remain),则在循环接收部分内容后就出现 由于系统缓冲区空间不足或队列已满,不能执行套接字上操作 的问题;如果我在每次Receive后Sleep(5),则就不会出现这个问题了,将Sleep的值改小,则又可能出现,Sleep值越小越容易出现;为什么?

如果将Receive函数的Size参数设置为一个固定较小的值,例如跟接收缓冲区大小一样为8192(程序中的 MinSize),则不用Sleep也不会出现问题。但我不知道这样会不会使接收效率降低。
...全文
1316 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
兔子-顾问 2014-10-20
  • 打赏
  • 举报
回复
引用 9 楼 yangyangqinqin 的回复:
但用异步接收比同步接收在效率和稳定性方面要好,有没有一些理论说法。
对于流设备,在分时操作系统上,你循环读取数据时会存在和硬件时序对不准的情况,比如底层还在接收,你已经开始获取缓存字节数,然后读取,等下一个周期,这之间可能会有大量数据读到,超出部分丢失或是其他小问题,丢包,错误的情况多。 异步接收其实反而是软件和硬件都同步了,硬件一段时间的读取完成,触发信号,你读取线程开始读,丢和误少很多。 没更多的理论依据,这是我猜的,之前做的一个socket功能测试结果如此。
yangyangqinqin 2014-10-20
  • 打赏
  • 举报
回复
引用 7 楼 sp1234 的回复:
另外,建议你最好使用异步 Receive,而不是同步 Receive。这样才能保证效率和稳定性。
这个可能是个好主意,只是控制上稍微麻烦一点,不是什么大问题。 我可以去测试一下异步接收是否还有这个问题。 但用异步接收比同步接收在效率和稳定性方面要好,有没有一些理论说法。
yangyangqinqin 2014-10-20
  • 打赏
  • 举报
回复
引用 5 楼 sp1234 的回复:
[quote=引用 2 楼 yangyangqinqin 的回复:] 貌似是说发送或接收太快就会出现这个错误,但还是有点不理解
不用理解了,只要是说“发送或接收太快就会出现这个错误”,那一定是他自己的程序设计有严重问题,而把问题找了个无关的理由。[/quote] 老大,你说了每一次Send不要大于10M,但我如果要发送80M的东西怎么办,我只能分8次发送。是的,我可以分8次发送,但我还是要用8次来循环发送,关键问题就是现在循环发送的时候出现了这个错误(其实我是接收的时候出了错误),那么请问这个程序设计上的严重问题在哪?是应该在每次发送之间要延时吗?如果是这样,那么请问这个延时的依据在哪?延时多少合适?
  • 打赏
  • 举报
回复
另外,建议你最好使用异步 Receive,而不是同步 Receive。这样才能保证效率和稳定性。
  • 打赏
  • 举报
回复
引用 4 楼 yangyangqinqin 的回复:
[quote=引用 3 楼 wuyazhe 的回复:] 1.自己拆开多个包 2.BeginReceive EndReceive
嗯,自己拆包是可以的,但我觉得拆成多个包分开进行发送接收也存在循环发送和接收的问题,因为我总共就是要发送接收这么多的东西,除非在发送和接收拆分后的包时利用进行一定量的延时。 至于异步接收,由于在一次异步接收时同样可能不会接收到我所要的所有数据,因此可能也需要多次异步接收才能完成,控制上稍显麻烦一点,至于多次异步接收的时候还会不会出现 “由于系统缓冲区空间不足或队列已满,不能执行套接字上操作 的问题” 这个问题,我倒是没测试过[/quote] 不要“觉得”,你还是实际去测试一下再说。 每一次Send不要大于10M。
  • 打赏
  • 举报
回复
引用 2 楼 yangyangqinqin 的回复:
貌似是说发送或接收太快就会出现这个错误,但还是有点不理解
不用理解了,只要是说“发送或接收太快就会出现这个错误”,那一定是他自己的程序设计有严重问题,而把问题找了个无关的理由。
yangyangqinqin 2014-10-20
  • 打赏
  • 举报
回复
引用 3 楼 wuyazhe 的回复:
1.自己拆开多个包 2.BeginReceive EndReceive
嗯,自己拆包是可以的,但我觉得拆成多个包分开进行发送接收也存在循环发送和接收的问题,因为我总共就是要发送接收这么多的东西,除非在发送和接收拆分后的包时利用进行一定量的延时。 至于异步接收,由于在一次异步接收时同样可能不会接收到我所要的所有数据,因此可能也需要多次异步接收才能完成,控制上稍显麻烦一点,至于多次异步接收的时候还会不会出现 “由于系统缓冲区空间不足或队列已满,不能执行套接字上操作 的问题” 这个问题,我倒是没测试过
兔子-顾问 2014-10-20
  • 打赏
  • 举报
回复
1.自己拆开多个包 2.BeginReceive EndReceive
yangyangqinqin 2014-10-20
  • 打赏
  • 举报
回复
貌似是说发送或接收太快就会出现这个错误,但还是有点不理解 因为我是顺序接收的,即等一次Receive函数返回后再进行下一次的Receive, 那么无论一次Receive的Size有多大,只要Receive函数返回,就表明该次接收已经正常完成了, 下一次的Receive应该不受任何影响才对, 为什么出现这个错误会受Receive函数的Size参数影响呢?
sunny906 2014-10-17
  • 打赏
  • 举报
回复
这个或许对你有帮助 http://bbs.csdn.net/topics/310027936

111,097

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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