himrpei 发表于 2014-10-29 22:09

关于 “socket 阻塞模式时,sendto 系统调用的行为” 的疑惑

本帖最后由 himrpei 于 2014-10-29 22:11 编辑

疑惑一:用 socket 系统调用创建的 socket 默认就是阻塞模式吧?


疑惑二:
man sendto 看到关于“阻塞”的描述如下:
Whenthemessagedoes not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in nonblocking I/O mode.In nonblocking mode it would fail with the error EAGAINorEWOULDBLOCK in this case.

根据如上描述,我这样做:
用 setsockopt 将创建的 socket 的 send buffer 设置为一个较小的值,比如 2050 。然后调用 sendto 通过这个 socket 发数据,数据的大小大于 send buffer 的值,比如 5000 。
本来想着,如果 socket 是阻塞模式,调用 sendto 进程应该卡在那不动才对。谁知程序直接报错返回,将 errno 设置为:ENOBUFS 。

man sendto 关于 ENOBUFS 的描述为:
Theoutputqueuefora network interface was full.This generally indicates that the interface has stopped sending, but may be caused by transient congestion.(Normally, this does not occurinLinux. Packets are just silently dropped when a device queue overflows.)

我的疑惑是,对于 sendto 来说,阻塞的含义到底是什么? “Theoutputqueuefora network interface was full” 时为什么没有发生阻塞,在 socket 设为阻塞模式的时候?

求哥哥、姐姐、大神、大师们解答下我的疑惑。不胜感激!

Hugo801122 发表于 2014-10-30 05:04

sendto这些函数应该是立刻返回的吧,recv阻塞的话就是会一直挂住等待接收完毕,否则一直挂住。不知道理解对不对。。
所以经常看人会开一个线程用来recv,不过很少说开一个单独线程来send的。

himrpei 发表于 2014-10-30 10:11

回复 2# Hugo801122

但是我看到 man 手册里对关于 sendto 的阻塞描述,sendto 也有阻塞这一说。
recv 的阻塞指的是当接收 buffer 里没有数据时卡在那里,直到有数据到来。

或许我真不应该考虑 sendto 的阻塞。

   

jackywgw 发表于 2014-11-03 16:23

套接字默认是阻塞的。

TCP有真正意义上的发送缓存,内核从应用进程的缓冲区复制数据到套接字的发送缓冲区,如果发送缓冲区没有空间,并且是阻塞套接字,那么进程将被阻塞直到有空间,
因为UDP套接字不存在真正的发送缓冲区,内核只是复制应该进程数据,并把它沿协议栈冠以UDP首部和IP首部.所以不会阻塞。
从你的man sendto中也可以看到,文中只提了是send函数会阻塞,而不是sendto。通常send用于TCP,sendto用于UDP。

回复 1# himrpei


   

linux_c_py_php 发表于 2014-11-05 10:28

tcp不是send么。
页: [1]
查看完整版本: 关于 “socket 阻塞模式时,sendto 系统调用的行为” 的疑惑