关闭套接字close还是shutdown

close

这个函数会对套接字引用计数-1,一旦发现引用计数到0,就会对套接字进行彻底释放,并且会关闭tcp两个方向的数据流。

因为套接字可以被多个进程共享,你可以理解为我们给每个套接字都设置了一个积分,如果我们通过fork的方式创建了子进程,套接字积分+1,如果我们调用一次close,套接字积分-1

close函数具体是如何关闭两个方向的数据流呢?

在输入方向,系统内核会将该套接字设置为不可读,任何操作都会返回异常。

在输出方向,系统内核尝试将发送缓冲区的数据发送给对端,并最后向对端发送一个FIN报文,接下来如果再对该套接字进行写操作,则会返回异常。

如果对端没有检测到套接字已经关闭,还继续发送报文,就会收到一个RST报文,告诉对端:“Hi,我已经关闭了,别再给我发送数据了”。

shutdown

shutdown可以关闭一个连接的方向

int shutdown(int sockfd, int howto)

howto是这个函数的设置选项,它的设置主要有三个选项

SHUT_RD(0):关闭连接的读方向,对该套接字进行读操作直接返回EOF。从数据角度来看,套接字上接收缓冲区已有的数据将被丢弃,如果再有数据到达,会对数据进行ACK,然后悄悄丢弃。也就是说,对端还会收到ACK,在这种情况下不知道发送的数据已经被丢弃了。

SHUT_WR(1):关闭连接的写方向,这就是常被称为半关闭的连接。此时,不管套接字引用计数的值是多少,都会直接关闭连接的写方向。套接字上发送缓冲区已有的数据将被立即发送出去,并发送给对端一个FIN报文。应用程序再对该套接字进行写操作将会报错。还是会接收对端的数据的。

SHUT_RW(2):关闭套接字的读和写两个方向。这个看起来和直接调用close没区别,但是还是有差别的。

1.close会关闭连接,并释放所有连接对应的资源,而shutdown并不会立刻主动释放掉套接字和所有的资源。

2.close存在引用计数的概念,并不一定会导致该套接字不可用, shutdown则不会管引用计数,直接使得该套接字不可用,如果别的进程还在使用该套接字,将会收到影响。

3.close的引用计数导致不一定会发出FIN报文(因为引用计数???),而shutdown则总是会发出FIN报文,这在我们打算关闭连接通知对端的时候,非常重要。

直接调用close和使用shutdown关闭写方向的过程如上图。

发布了47 篇原创文章 · 获赞 39 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_28119741/article/details/104113619