Linux 网络编程详解九

TCP/IP协议中SIGPIPE信号产生原因
1.假设客户端socket套接字close(),会给服务器发送字节段FIN;
2.服务器接收到FIN,但是没有调用close(),因为socket有缓存区,所以服务器仍然可以向客户端发送数据。
3.如果这种状态下服务器向客户端发送数据,将会引起TCP/IP协议进行RST段重置,导致服务器向当前进程发送SIGPIPE信号,
  SIGPIPE信号的默认动作是关闭当前进程。
SIGPIPE信号产生的本质原因是管道的一端已经关闭,另一端却继续写入数据。
所以在网络编程中必须要捕捉SIGPIPE信号,因为不确定哪个端会突然close()。
   在TCP/IP协议中,假设在服务器端,父进程负责accept()连接,子进程负责与客户端通信交互,如果一个客户端socket文件描述符,
在父进程中没有调用close()函数关闭socket文件描述符,但是在子进程中调用close()函数关闭了socket文件描述符,那么子进程将无
法使用这个socket文件描述符read()或者send()数据,但是这个socket文件描述符仍然存在,因为父进程还引用着这个socket文件描述
符,文件表中的描述符引用不是0,因此服务器端不会向客户端发送FIN字节段,客户端就不会知道服务器端实际上已经无法read和send数据,
导致客户端可以发送数据,却接收不到数据,并且网络TCP/IP协议的状态都是ESTABLISHED状态(已连接状态)。所以多进程的服务器端需
要在父进程中关闭客户端socket文件描述符。

 

close()函数
#include<unistd.h>
int close(int sockfd);
功能:close()函数关闭文件读写两个数据传输方向。
close 一个套接字的默认行为是把套接字标记为已关闭,然后立即返回到调用进程,该套接字描述符不能再由调用进程使用,即它不能再作为read或write的第一个参数,
然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。
多进程并发服务器中,父子进程共享着套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,
描述符引用计数会相应的减一,当引用计数仍大于零时,这个close调用就不会引发TCP的四路握手断连过程

 

shutdown()函数
#include<sys/socket.h>
int shutdown(int sockfd, int how);
功能:shutdown()函数也可以用来关闭文件描述符,但是可以通过参数how来设置单独的关闭文件的读或者写

参数how
--SHUT_RD 关闭文件读数据传输
--SHUT_WR 关闭文件写数据传输
--SHUT_RDWR 关闭文件读写数据传输

终止网络连接的通用方法是调用close函数。但使用shutdown能更好的控制断连过程(使用第二个参数)。

 

close() 与 shutdown() 的区别
close()函数会关闭套接字,如果有其他的进程共享着这个套接字,那么它仍然是打开的,这个连接仍然可以用来读和写,并且有时候这是非常重要的 ,特别是对于多进程并发服务器来说。
shutdown()会切断进程共享的套接字的所有连接,不管这个套接字的引用计数是否为零,那些试图读得进程将会接收到EOF标识,
那些试图写的进程将会检测到SIGPIPE信号,同时可利用shutdown的第二个参数选择断连的方式。

 

posted on 2016-12-08 11:26  寒魔影  阅读(399)  评论(0编辑  收藏  举报

导航