Linux 中write()函数的出错情况及处理

来源:互联网 发布:环保软件项目 编辑:程序博客网 时间:2024/05/17 06:21
 write函数首先将进程需要发送的数据先放在进程缓冲区中,然后向socket的发送缓冲区进行拷贝,在此,可能出现这样情况,即当进程缓冲区中的数据量大于此时发送缓冲区中所能接受的数据量时,若此时处于阻塞模式,应用进程将会被挂起,直到进程缓冲区中的数据全部拷贝到发送缓冲区中,注意此时内核也不会返回write函数,因此,在阻塞模式下,若write函数正常返回,这也并不代表数据已经完成被对方进程接收,至多只能说明数据已经被发送缓冲区完全接受;若是处于非阻塞模式,此时write操作将会失败,内核会立即返回EAGAIN错误,在此需要声明的是,有时候在某些地方说会返回EWOULDBLOCK错误,其实二者本质一样,只是分别用于不同的系统罢了,前者主要是出现于GNU系统,,而后者主要出现在类BSD系统。  www.2cto.com  
 

【引申1】阻塞与非阻塞的转换:切换socket fd的阻塞标志。
int  fcntl(int fd , int cmd)
int  fcntl(int fd,int cmd,long arg)
其中cmd代表要操作的命令,常见有:
F_GETFL:取得fd的当前状态标志
F_SETFL:设置fd的当前状态标志
[cpp]
flags = (long) fcntl(pc->fd, F_GETFL);  
bflags = flags & ~O_NONBLOCK; /* clear non-block flag, i.e. block */  
fcntl(pc->fd, F_SETFL, bflags);  
 
【引申2】Linux中发送缓存大小的查看:
sysctl -a | grep net.ipv4.tcp_wmem
net.ipv4.tcp_wmem = 4096 16384 81920 (这三个值分别代表发送缓冲区的最少字节数,默认字节数以及最多字节数)  www.2cto.com  
2. write常见错误以及原因分析:
    前面已经说过EAGAIN错误出现的原因,下面主要讲解EPIPE错误是在何种情景下产生的。
    我们知道TCP连接需要三次握手,而退出需要四个过程,而EPIPE则是产生于进程socket的退出过程中,对应上面的原理图,若B端的进程已经主动关闭(发送FIN),但是A端因为各种原因(主要是未同步),未能知晓并仍然向对方发送数据,此时A端内核会返回EPIPE错误,它会发送SIGPIPE信号给进程A,默认情况下,进程将会自动退出。
    最近在做项目过程中,因为Apache server端的keep-alive配置时间过短,导致过早发出FIN,而使得client端的socket出现EPIPE错误,最后将keep-alive时间配置稍长点,一切问题OK
0 0
原创粉丝点击