免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: yulc
打印 上一主题 下一主题

linux下非阻塞的tcp研究 [复制链接]

论坛徽章:
0
31 [报告]
发表于 2007-07-31 11:24 |只看该作者
好象不是你说的这样。

你可以实验,写一个阻塞的TCP,先send 1 个字节(1次),成功后将NIC 拔掉,然后再SEND 1个字节(2次), 然后再1个字节(3次)

2次可以返回成功的。3次失败。

该问题同原来争吵的feof问题道理一样。

原帖由 醉卧水云间 于 2007-7-31 11:03 发表
建议flw还是去补习一下网络编程吧,阻塞模式下,必须发到对端函数才返回。

论坛徽章:
38
2017金鸡报晓
日期:2017-02-08 10:39:4215-16赛季CBA联赛之深圳
日期:2023-02-16 14:39:0220周年集字徽章-年
日期:2022-08-31 14:25:28黑曼巴
日期:2022-08-17 18:57:0919周年集字徽章-年
日期:2022-04-25 13:02:5920周年集字徽章-20	
日期:2022-03-29 11:10:4620周年集字徽章-年
日期:2022-03-14 22:35:1820周年集字徽章-周	
日期:2022-03-09 12:51:3220周年集字徽章-年
日期:2022-02-10 13:13:4420周年集字徽章-周	
日期:2022-02-03 12:09:4420周年集字徽章-20	
日期:2022-01-25 20:14:2720周年集字徽章-周	
日期:2022-01-13 15:12:33
32 [报告]
发表于 2007-07-31 11:48 |只看该作者
原帖由 思一克 于 2007-7-31 11:24 发表
好象不是你说的这样。

你可以实验,写一个阻塞的TCP,先send 1 个字节(1次),成功后将NIC 拔掉,然后再SEND 1个字节(2次), 然后再1个字节(3次)

2次可以返回成功的。3次失败。

该问题同原来争吵 ...


你这是欺骗系统的方式,拔掉网线后系统知道被拔是需要时间的。你可以等一段时间再发送试试,结果应不同。

还有就是系统因为效率上的原因,没有严格按send语意来做,send语意就是返回成功就是保证发送成功,但处理起来象你这样1个字节就发去确认没有效率,考虑到效率问题,发一个字节可能不会立刻发出等待确认,他要等一段时间或者超时,或者缓冲满再发出,然后等对方确认函数返回。

如果你每次发出的包足够长,则当时就可以确认网络断了,因为足够长的包会立刻发出并等对方确认。

你举的这个例子不可以用来反驳send仅仅是发到缓冲然后立刻返回,系统只是出于效率上的考虑才对这种小包进行特别对待,正常的包还是要等反馈再返回的。

论坛徽章:
0
33 [报告]
发表于 2007-07-31 11:52 |只看该作者
越说越不明白了,呵呵。
不要人身攻击,无任何意义。
解决方式:
1. 看linux中的相关代码
2. 发送信件,咨询网络部分的linux kernel维护人员,不过回复的希望渺茫。
3. 大家讨论。

[ 本帖最后由 dzbjet 于 2007-7-31 11:54 编辑 ]

论坛徽章:
0
34 [报告]
发表于 2007-07-31 11:53 |只看该作者
send 可能要将一个字节经过很多设备发送到地球那一边。而且有时候网络又很慢。不可能等完成。再说了,只要对方不发确认,你如何知道完成了? 发了确认都未必见得是真的。

所以拔网络线后第2次可以成功返回没有什么问题。设计的就是这样的。而通过第2次,才有第3次的失败。

原帖由 醉卧水云间 于 2007-7-31 11:48 发表


你这是欺骗系统的方式,拔掉网线后系统知道被拔是需要时间的。你可以等一段时间再发送试试,结果应不同。

还有就是系统因为效率上的原因,没有严格按send语意来做,send语意就是返回成功就是保证发送成功 ...

论坛徽章:
0
35 [报告]
发表于 2007-07-31 11:58 |只看该作者
man send.

RETURN VALUE
       On  success,  these  calls return the number of characters sent.  On error, -1 is
       returned, and errno is set appropriately.

成功代表内容被成功地传输到网络了,不代表到达远方目的地。

还有看以下如此多的错误返回,也可以知道send绝对不是将内容放到本地buffer就返回(只要buffer有空间就成功返回)那样简单。


ERRORS
       These are some standard errors generated by the socket layer.  Additional  errors
       may  be  generated  and  returned from the underlying protocol modules; see their
       respective manual pages.

       EACCES (For Unix domain sockets, which are identified by pathname) Write  permisâ

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
36 [报告]
发表于 2007-07-31 12:20 |只看该作者
各位大师..讨论之余能否给一些经验值...在视频传输应用中,非阻塞的情况下sendbuf_len or recvbuf_len 在TCP UDP下通常设为多大

论坛徽章:
0
37 [报告]
发表于 2007-07-31 12:43 |只看该作者
原帖由 思一克 于 2007-7-31 11:58 发表
man send.

RETURN VALUE
       On  success,  these  calls return the number of characters sent.  On error, -1 is
       returned, and errno is set appropriately.

成功代表内容被成功地传输到 ...

对,在阻塞模式下是这样的,send将数据发到网络上就ok了,不必等ack。而且一般tcp的实现是2次一个ack,所以要马上收到ack是不可能的。
非阻塞的时候好像就是拷贝到缓冲区。
还有一个证明,就是有个SO_SNDBUG,设为0的时候。数据应该会这接发出去吧。

论坛徽章:
38
2017金鸡报晓
日期:2017-02-08 10:39:4215-16赛季CBA联赛之深圳
日期:2023-02-16 14:39:0220周年集字徽章-年
日期:2022-08-31 14:25:28黑曼巴
日期:2022-08-17 18:57:0919周年集字徽章-年
日期:2022-04-25 13:02:5920周年集字徽章-20	
日期:2022-03-29 11:10:4620周年集字徽章-年
日期:2022-03-14 22:35:1820周年集字徽章-周	
日期:2022-03-09 12:51:3220周年集字徽章-年
日期:2022-02-10 13:13:4420周年集字徽章-周	
日期:2022-02-03 12:09:4420周年集字徽章-20	
日期:2022-01-25 20:14:2720周年集字徽章-周	
日期:2022-01-13 15:12:33
38 [报告]
发表于 2007-07-31 12:45 |只看该作者
从原理上,发送放无法知道本次反送内容是否被对方收到,因为网络太复杂了,太遥远了,谁知道包正走着呢前方海底光缆就地震断了?

所以,TCP的上层应用协议都要自己确认,比如SMTP的250,220,等返回。POP3的+OK, +ERR。
FTP在应用层的验证确认估计更严格。

还有,我的拔NIC的例子,你可以将包变为128字节。只要有一个反例,就可以证明全部了。


原帖由 思一克 于 2007-7-31 11:58 发表
man send.

RETURN VALUE
       On  success,  these  calls return the number of characters sent.  On error, -1 is
       returned, and errno is set appropriately.

成功代表内容被成功地传输到 ...



当你发送的东西超过缓冲,则你的send返回后必定已被对方确认收到,但不是全部,是缓冲装不下的那部分字节或者更多的字节,send返回10000,可能被确认接受的是5000,总之超过缓冲区限制的字节必定有一些包需要对方确认,但send返回的值并不是可依赖的值,这里面主要还是缓冲的原因,如果缓冲为0,则发多少就确认多少。如果你发一个大数据包,则等对方的确认就需要很长的过程,你工作线程等在那里,是因为等待对方确认,所以是长过程。

非阻塞下,等的不是你的工作线程,是系统在等,完成后告诉你可以继续发。

man send中说发送成功不代表对方收到也是有道理的,因为有缓冲在中间,缓冲能存下的这部分不能确保对方收到,所以它就模糊的说你发的所有数据我不保证对方收到,实际是超过缓冲的那部分是肯定会被收到的,因效率问题,缓冲的部分变的不那么确定,这只是技术上的实现问题。

[ 本帖最后由 思一克 于 2007-7-31 12:54 编辑 ]

论坛徽章:
0
39 [报告]
发表于 2007-07-31 12:49 |只看该作者
在阻塞模式下,如果发送包大于缓冲区长度,那中间肯定有一次要把发送端缓冲区的数据通过网络传送到接受端缓冲区。如果这时网络或者对端有问题,send会失败。

还有在发送端已知对方关闭或连接断掉的情况,send肯定会返回失败。

但是重点在于发送包长度小于发送缓冲区长度,而且发送端还不知对端情况时会怎么办?我也按照思一克的实验做了一下,证明了(至少是某些系统)send并不会真正触发网络传送。条件是小于缓冲区长度。

论坛徽章:
0
40 [报告]
发表于 2007-07-31 12:49 |只看该作者
原帖由 flw 于 2007-7-31 11:21 发表

哦?把你的测试代码发上来。



哦,刚刚测了下,我说得不太对.
在接收端主动关闭后,如果发送端继续send,第一次会依然填充本地的发送缓存,如果缓存不够,才会返回-1,如果够,则正确返回;
但接下来,发送端应该是继续等待下一次可读或可写的信号,并且会收到可读的信号,然后recv时会发现返回0,
我说的是如果发送端没处理这个信号,再次send,那么就出错了,得到SIGPIPE.

我是临时在我的项目工程中测的,代码不太好贴...
测试步骤是:
1. A和B建立tcp,将A设为非阻塞方式;
2. A调用send发送1k数据给B,B也进行了recv;
3. 然后在A在第二次send时打上断点,停住;
4. 将B程序退出;
5. A继续第二次调用send,返回正确;
6. A第三次调用send,进程收到SIGPIPE,退出.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP