首页 新闻 会员 周边

请教关于socket编程的send函数!(TCP)

0
悬赏园豆:200 [已关闭问题] 关闭于 2010-08-08 20:16

请教关于socket编程的send函数!(TCP)

刚看到一篇文章是关于 socket编程在TCP的情况下,使用send函数时,阻塞与非阻塞的区别,详见下面这篇文章:
http://www.cppblog.com/artmouse/archive/2005/12/14/1762.aspx

这篇文章的大意是讲:
 1 在socket阻塞时,send一定会等到将想要发送的数据copy到缓冲区为止(不管要发送的数据有多大),也就是说这个时候send返回的长度一定等于要发送的数据的长度,所以此时也不用循环send;
 2 在socket非阻塞时,send返回的长度可能小于要发送的数据的长度,所以此时用循环send;


但是我做的实验发现:
  a 不论要发送的数据要多大(我发送的数据大小是1M,发送缓冲区是8K)
  b 不论阻塞还是非阻塞
send返回的值总是等于要发送的数据的长度,也就是说一次就发送完了(或者说Copy到缓冲区了)。

请问:
  i http://www.cppblog.com/artmouse/archive/2005/12/14/1762.aspx 这篇文章讲的是否对?(我认为这篇文章对)
  ii 我的实验结果怎么解释
PS:我的实验环境是win7,TCP 的server,client在同一台机器。

问题补充: 测试代码这放不下了!想看测试代码的请看: http://topic.csdn.net/u/20100731/16/18e2f905-124e-485b-b0e3-3fd9973c48de.html?58188
BourneHan的主页 BourneHan | 初学一级 | 园豆:0
提问于:2010-08-01 19:51
< >
分享
所有回答(3)
-1

你的实验方法不对,不能在同一个机器上做,同一台机器上发,数据包发到环回地址上直接反弹了,底层实际上是通过命名管道走的,没有走网卡。由于速度非常快,所以异步发送时,一次可以全部发送完,这并不代表异步发送可以和同步发送一样处理。你如果向一个网速较慢的机器上发,你就会发现实际发送的数据量和你要发送的有区别了。

eaglet | 园豆:17139 (专家六级) | 2010-08-02 07:56
专家早啊!那请问:即使是走命名管道,那socket的发送缓冲和接受缓冲也不起作用了么?因为我发现socket的发送缓冲和接受缓冲都是8K,那么发送的1M数据去哪了呢?总得有个地方吧?不会在网上(或命名管道里)吧?
支持(0) 反对(0) BourneHan | 园豆:0 (初学一级) | 2010-08-02 08:28
@BourneHan: 由于是走命名管道,根本用不到发送缓冲区,你就是发1G,它也一下拷贝过去,按缓冲区那样发对于命名管道来说是多此一举。你必须用两台机器来测试才能看到效果。
支持(1) 反对(0) eaglet | 园豆:17139 (专家六级) | 2010-08-04 10:26
我不同意您的说法,因为即使对于命名管道来说,它也一下拷贝过去 另一端也不可能有那么大的缓冲区收数据。whatever 谢谢你!我查到一些资料如下: You can change the amount of Winsock kernel buffer allocated to the socket using the SO_SNDBUF option (it is 8K by default). If necessary, Winsock can buffer significantly more than the SO_SNDBUF buffer size.
支持(0) 反对(1) BourneHan | 园豆:0 (初学一级) | 2010-08-08 20:12
0

如果你发送1M,就给你1M的缓冲区,要是你发送1G,那还不得给你1G的缓冲区.所谓缓冲区,是指衔接多个速率不一致的I/O设备的中转站,通过一定的算法平衡速率不一致造成的CPU时钟周期浪费.因此,这个buffer的东西有个固定分配算法,有个基数,然后有个倍数,只有当写速率大于发速率的时候,才会增加BUFFER的大小.

Launcher | 园豆:45045 (高人七级) | 2010-08-02 09:00
大哥,你想说啥? 我是说要发送1M的数据,socket有8K的缓冲区(收发都是)。另外您所讲的"因此,这个buffer的东西有个固定分配算法,有个基数,然后有个倍数,只有当写速率大于发速率的时候,才会增加BUFFER的大小."是从哪得知的?我很想知道。因为我在MSDN中没看到过相关介绍,请指教!!谢谢! 另外我还真试了,发送1g数据也是一次发送成功,只是阻塞的时间长了些!
支持(0) 反对(0) BourneHan | 园豆:0 (初学一级) | 2010-08-02 15:55
你可以通过 setsockopt 设置发送缓冲区和接收缓冲区的大小。如果你要发送的数据比较大,设置N * 1024的大小,但也不能太大。
支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2010-08-03 13:32
你把你的发送缓冲区大小设置为 1,然后你再发送 1G 的数据,你就可以看到阻塞和非阻塞的区别了。
支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2010-08-03 13:38
缓冲区,是衔接内存和网卡之间的中转站,这是一个消费者-生产者模型,系统使用内核级的api从缓冲区读取数据然后交给网卡,你在内存中写入再大的数据,它都要按照缓冲区的大小一点一点的往缓冲区拷贝。你理解缓冲区的作用后,再回头看阻塞和非阻塞的解释就应该明白了。
支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2010-08-03 13:55
谢谢你,本来想把分给你一部分的,但我发现我没有分(我是菜鸟,请原谅!)。 You can change the amount of Winsock kernel buffer allocated to the socket using the SO_SNDBUF option (it is 8K by default). If necessary, Winsock can buffer significantly more than the SO_SNDBUF buffer size.
支持(0) 反对(0) BourneHan | 园豆:0 (初学一级) | 2010-08-08 20:13
0

socket.NoDelay = true;

live-evil | 园豆:140 (初学一级) | 2010-08-02 10:24
这位兄弟,您这是JAVA,还是C#??? 不带这样的,你的多说两句啊!
支持(0) 反对(0) BourneHan | 园豆:0 (初学一级) | 2010-08-02 15:59
@BourneHan:C# 具体:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket_properties%28v=VS.95%29.aspx
支持(0) 反对(0) live-evil | 园豆:140 (初学一级) | 2010-08-06 15:16
我知道您说的这是要关闭Nagle算法是吧?但我认为这样意义应该不大。也谢谢你!本来想给你分的,但我发现我没有分(我是菜鸟,请原谅!)。
支持(0) 反对(0) BourneHan | 园豆:0 (初学一级) | 2010-08-08 20:15
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册