socket关闭close和shutdown(转)

来源:互联网 发布:ibatis xml 引用sql 编辑:程序博客网 时间:2024/05/17 23:15

socket关闭有2个close,shutdown

他们之间的区别:

close-----关闭本进程的socket id,但链接还是开着的,用这个socket id的其它进程还能用这个链接,能读或写这个socket id

shutdown--则破坏了socket 链接,读的时候可能侦探到EOF结束符,写的时候可能会收到一个SIGPIPE信号,这个信号可能直到

socket buffer被填充了才收到,shutdown还有一个关闭方式的参数,0 不能再读,1不能再写,2 读写都不能。

===============================================================================================================

socket 多进程中的shutdown, close使用

当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:

close(sockfd);

你也可以调用shutdown()函数来关闭该socket。该函数允许你只停止在某个方向上的数据传输,而一个方向上的数据传输继

续进行。如你可以关闭某socket的写操作而允许继续在该socket上接受数据,直至读入所有数据。

int shutdown(int sockfd,int how);

Sockfd是需要关闭的socket的描述符。参数 how允许为shutdown操作选择以下几种方式:

    SHUT_RD:关闭连接的读端。也就是该套接字不再接受数据,任何当前在套接字接受缓冲区的数据将被丢弃。进程将不能对该

套接字发出任何读操作。对TCP套接字该调用之后接受到的任何数据将被确认然后无声的丢弃掉。

    SHUT_WR:关闭连接的写端,进程不能在对此套接字发出写操作

    SHUT_RDWR:相当于调用shutdown两次:首先是以SHUT_RD,然后以SHUT_WR

使用close中止一个连接,但它只是减少描述符的参考数,并不直接关闭连接,只有当描述符的参考数为0时才关闭连接。

shutdown可直接关闭描述符,不考虑描述符的参考数,可选择中止一个方向的连接。

注意:

    1>. 如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程都调用了close,套

接字将被释放。

    2>. 在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信. 如果一个进程close(sfd)将不会

影响到其它进程. 得自己理解引用计数的用法了. 有Kernel编程知识的更好理解了.

同事发现的该问题, 认为很重要就记下了!

===============================================================================================================

 

如果有五个进程使用该 socket id 则这个socket 描述符参考数则有五个,当所有进程都close()了这样参考数就等于0,该socket 就真的关闭释放了。

 

 

 

================================

 

摘要:对于网络TCP面向连接的程序,它需要在某个时候终止已经存在的连接。用户可以主动终止一个连接,这很重要,尤其对于服务器进程而言,因为一个进程可以同时打开的连接是有限的,如果不在某个时候主动终止已有的连接,那么对于服务器进程来说,它总会在某个时候因为无法打开新连接而失败。

对于UNIX系统而言,无论是一般的文件描述符,还是网络中使用的套接字都是描述字的范围,所以它们都可以用close函数来完成关闭的任务,然后对于网络套接字这一个特殊的描述字,我们却可以使用更加丰富的shutdown函数完成有选择的关闭。下面我们先来看看这个两个函数:

#include<unistd.h>

int close(int fd)

返回:0——成功, -1——失败

#include<sys/socket.h>

int shutdown(int sockfd, int howto)

返回:0——成功, -1——失败

 

让我们来回忆一下,一个文件描述符关联着一个实际的文件——不管这个文件是什么,普通文件或网络套接口等等,但是多个打字可以同时与一个文件关联,并且内核维护一个文件引用计数。正常情况下,close函数不武断地释放一个描述字关联的文件,除了这个引用计数为0的时候,并且无论如何,当对一个描述字调用了close函数,用户无法再次使用这个描述字。这是close相对shutdown的两点差别,相应地shutdown是针对socket套接口定制的函数,所以它会做的更好。

shutdown函数不是参考引用计数,它会直接关闭相应的socket套接口,无论引用计数是多少。我们还知道,socket套接口是全双工的,也就是用户可以读,也可以写。存在一个这样的情况,此时用户已经把所有要写的数据都写完了,他想告诉对等端这一点;或者用户把所有要读的数据都读完成了,同样要告诉对等端。此时就是关闭读这一半或写这一半,使用shutdown可以完成这一个。系统定义了3个宏,这3个宏分别用作shutdown的后一个参数:

  • SHUT_RD:关闭读这一半,此时用户不能再从这个套接字读数据,这个套接口接收到的数据都会被丢弃,对等方不知道这个过程。
  • SHUT_WR:相应地关闭写这一半,此时用户不能再向套接字中写数据,内核会把缓存中的数据发送出去,接着不会再发送数据,对等端将会知道这一点。当对等端试图去读的时候,可能会发生错误。
  • SHUT_RDWR:关闭读与写两半,此时用户不能从套接字中读或写。它相当于再次调用shutdown函数,并且一次指定SHUT_RD,一次指定SHUT_WR。

 

刚才我写完了服务器编程之fork并行模式,这个文章中我们使用close函数,试问一下:我们可以使用shutdown函数代替吗?简单的思考之后,我们知道不可以使用shutdown函数代替,因为我们在子进程中只是想解除sockfd与那个监听套接口的关联,并不想释放这个套接口,原因是在父进程还要使用它;相应在父进程我也只是想解除cfd与其套接口的关联,我们在子进程还需要使用cfd。从这个例子中可以看到,close与shutdown有各自的用处,并不能相互代替,就算在socket套接字这一特定情况下也如此。

原创粉丝点击