
send的意思
-
2023年2月19日发(作者:)send返回值
在Unix系统下,如果send、recv、write在等待协议传送数据时,socket被shutdown,调⽤send的进程会接收到⼀个SIGPIPE信
号,进程对该信号的默认处理是进程终⽌。此种情况应⽤就很难查出处理进程为什么退出。
SIGPIPE信号:
对⼀个已经收到FIN包的socket调⽤read⽅法,如果接收缓冲已空,则返回0,这就是常说的表⽰连接关闭.但第⼀次对其调⽤write⽅法
时,如果发送缓冲没问题,会返回正确写⼊(发送).但发送的报⽂会导致对端发送RST报⽂,因为对端的socket已经调⽤了close,完全关
闭,既不发送,也不接收数据.所以,第⼆次调⽤write⽅法(假设在收到RST之后),会⽣成SIGPIPE信号,导致进程退出。如果对SIGPIPE进
⾏忽略处理,⼆次调⽤write⽅法时,会返回-1,同时errno置为SIGPIPE.
处理⽅法:
在初始化时调⽤signal(SIGPIPE,SIG_IGN)忽略该信号(只需⼀次),SIGPIPE交给了系统处理。此时send、recv或write函数将返
回-1,errno为EPIPE,可视情况关闭socket或其他处理
SIGPIPE被忽略的情况下,如果服务器采⽤了fork的话,要收集垃圾进程,防⽌僵⼫进程的产⽣,可以这样处
理:signal(SIGCHLD,SIG_IGN); 交给系统init去回收。这样⼦进程就不会产⽣僵⼫进程了。
在Linux环境下开发经常会碰到很多错误(设置errno),其中EAGAIN是其中⽐较常见的⼀个错误(⽐如⽤在⾮阻塞操作中)。
从字⾯上来看,是提⽰再试⼀次。这个错误经常出现在当应⽤程序进⾏⼀些⾮阻塞(non-blocking)操作(对⽂件或socket)的时候。例如,以
O_NONBLOCK的标志打开⽂件/socket/FIFO,如果你连续做read操作⽽没有数据可读。此时程序不会阻塞起来等待数据准备就绪返
回,read函数会返回⼀个错误EAGAIN,提⽰你的应⽤程序现在没有数据可读请稍后再试。
⼜例如,当⼀个系统调⽤(⽐如fork)因为没有⾜够的资源(⽐如虚拟内存)⽽执⾏失败,返回EAGAIN提⽰其再调⽤⼀次(也许下次就能成功)。
Linux-⾮阻塞socket编程处理EAGAIN错误
在linux进⾏⾮阻塞的socket接收数据时经常出现Resourcetemporarilyunavailable,errno代码为11(EAGAIN),这是什么意思?
这表明你在⾮阻塞模式下调⽤了阻塞操作,在该操作没有完成就返回这个错误,这个错误不会破坏socket的同步,不⽤管它,下次循环接着
recv就可以。对⾮阻塞socket⽽⾔,EAGAIN不是⼀种错误。在VxWorks和Windows上,EAGAIN的名字叫做EWOULDBLOCK。
另外,如果出现EINTR即errno为4,错误描述Interruptedsystemcall,操作也应该继续。
最后,如果recv的返回值为0,那表明连接已经断开,我们的接收操作也应该结束。
当客户通过Socket提供的send函数发送⼤的数据包时,就可能返回⼀个EGGAIN的错误。该错误产⽣的原因是由于send
函数中的size变量⼤⼩超过了tcp_sendspace的值。tcp_sendspace定义了应⽤在调⽤send之前能够在kernel中缓存的数据量。当应⽤
程序在socket中设置了O_NDELAY或者O_NONBLOCK属性后,如果发送缓存被占满,send就会返回EAGAIN的错误。
为了消除该错误,有三种⽅法可以选择:
1.调⼤tcp_sendspace,使之⼤于send中的size参数
---no-p-otcp_sendspace=65536
2.在调⽤send前,在setsockopt函数中为SNDBUF设置更⼤的值
1.你⾃⼰的缓冲区满了,会返回EAGAIN。
2.你的没满,对⽅的缓冲区满了,肯定不关你事,可能会发送不成功,但是协议栈提供的系统调⽤,只管数据成功从你的缓冲区发出去,之后
⼈家因为缓冲区满收不到数据,tcp⾃⼰有重传机制(参考Tcp/ip详解卷1)。
send()适⽤于已连接的数据包或流式发送数据。对于数据报类套接⼝,必需注意发送数据长度不应超过的IP包最⼤长度。IP包最⼤长度在调
⽤返回的WSAData的iMaxUdpDg元素中。如果数据太长⽆法⾃动通过下层协议,则返回WSAEMSGSIZE错误,数据不会被发送。
请注意成功地完成send()调⽤并不意味着到达。
如果传送系统的空间不够保存需传送的数据,除⾮套接⼝处于⾮阻塞I/O⽅式,否则send()将阻塞。对于⾮阻塞SOCK_STREAM类型的套
接⼝,实际写的数据数⽬可能在1到所需⼤⼩之间,其值取决于本地和远端主机的⼤⼩。可⽤调⽤来确定何时能够进⼀步发送数据。