UNIX网络编程:shutdown与close函数的区别

假设server和client 已经建立了连接,server调用了close, 发送FIN 段给client(其实不一定会发送FIN段,后面再说),此时server不能再通过socket发送和接收数据,此时client调用read,如果接收到FIN 段会返回0,但client此时还是可以write 给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据后应答一个RST段,表示服务器已经不能接收数据,连接重置,client收到RST段后无法立刻通知应用层,只把这个状态保存在TCP协议层。如果client再次调用write发数据给server,由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。

有时候代码中需要连续多次调用write,可能还来不及调用read得知对方已关闭了连接就被SIGPIPE信号终止掉了,这就需要在初始化时调用sigaction处理SIGPIPE信号,对于这个信号的处理我们通常忽略即可,signal(SIGPIPE, SIG_IGN); 如果SIGPIPE信号没有导致进程异常退出,write返回-1并且errno为EPIPE。

#include <unistd.h>
 int close(int fd);

close 关闭了自身数据传输的两个方向。

close一个TCP套接字的默认行为是把该套接字标记成已关闭,然后立即返回到调用进程。该套接字描述符不能再由调用进程使用,也就是说它不能作为read或write的第一个参数。然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。

我们可以通过SO_LINGER套接字选项可以用来改变TCO套接字的这种默认行为。

终止网络连接的通常方法是调用close函数。不过close有两个限制,却可以使用shutdown来避免。

(1)close把描述符的引用计数减1,仅在该计数变为0时才关闭套接字。使用shutdown可以不管引用计数就激发TCP的正常连接终止序列。

(2)close终止读和写两个方向的数据传送。既然TCP连接是全双工的,有时候我们需要告知对端我们已经完成了数据发送,即使对端仍然有数据要发送给我们。

#include <sys/socket.h>
int shutdown(int sockfd,int howto);
      返回:若成功则为0,若出错则为-1

该函数的行为依赖于howto参数的值:

SHUT_RD    关闭连接的读这一半,套接字中不在有数据可接收,而且套接字接收缓冲区中的现有数据都被丢失。进程不能再对这样的套接字调用任何读函数。对一个TCP套接字这样调用shutdown函数后,由该套接字接收的来自对端的任何数据都被确认,然后悄然丢弃。

SHUT_WR    关闭连接的写这一半,对于TCP套接字,这称为半关闭。当前留在套接字发送缓冲区中的数据将被发送掉,后跟TCP的正常连接终止序列。我们已经说过了,不管套接字描述符的引用计数是否等于0,这样的写半部关闭照样执行。进程不能再对这样的套接字调用任何写函数。

SHUT_RDWR  连接的读半部和写半部都关闭,这与调用shutdown两次等效:第一次调用指定SHUT_RD,第二次调用指定SHUT _WR。

作者:csdn博客 ctthuangcheng

查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/OS/unix/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索数据
, 函数
, 套接字
, 信号
, close
, shutdown
套接字连接已终止
,以便于您获取更多的相关知识。

时间: 2024-10-30 07:58:49

UNIX网络编程:shutdown与close函数的区别的相关文章

select-调试信息无法打印 unix网络编程

问题描述 调试信息无法打印 unix网络编程 如代码注释信息所示,应该是缓冲区的问题,但是stderr是无缓冲区的,而且也使用了fflush函数,也没用.希望能有人指点指点,谢谢 #include "globle.h" #define port 8082 int main( int argc, char *argv[] ){ fprintf(stderr, "11111111111n");//无法打印 fflush(stdout); int listenfd,soc

UNIX网络编程之旅-配置unp.h头文件环境

最近在学习Unix网络编程(UNP),书中steven在处理网络编程时只用了一个#include "unp.h"  相当有个性并且也很便捷 于是我把第三版的源代码编译实现了这个过程,算是一种个性化的开发环境的搭建吧,顺便把过程记录下来,以便自己以后查阅.   首先去网上找到源代码包unpv.13e.tar.gz 一找一大堆 解压缩到你的某个目录,unpv13e里面大致有这些目录 ├── aclocal.m4 ├── advio ├── bcast ├── config.guess ├─

unix网络编程问题(初学者)

问题描述 unix网络编程问题(初学者) 除了头文件和打印外,我都是照着书敲的,但是结果不对,希望帮我解决,谢谢啦!!!书上的正确结果是一串表示时间的字符 问题:connect error 在建立服务器的连接出错输入:./get_tima 192.168.154.130(ip地址我用ifconfig得到的,我也用127.0.0.1做过一样得不到想要的结果)结果:connect errorread error 出处:unix网络编程 1.2-一个简单的时间获取客户程序 #include#inclu

UNIX网络编程:fcntl函数

fcntl函数提供了与网络编程相关的如下特性: 非阻塞式I/O.  通过使用F_SETFL命令设置O_NONBLOCK文件状态标志,我们可以把一个套接字设置为非阻塞型. 信号驱动式I/O. 通过使用F_SETFL命令设置O_ASYNC文件状态标志,我们可以把一个套接字设置成O_ASYNC,一旦其状态发生变化,内核就产生一个SIGIO信号. F_SETOWN命令允许我们指定用于接收SIGIO和SIGURG信号的套接字属主(进程ID或进程组ID).其中SIGIO信号是套接字被设置为信号驱动式I/O型

UNIX网络编程:I/O复用:select和poll函数

我们看到TCP客户同时处理两个输入:标准输入和TCP套接字.我们遇到的问题是就在客户阻塞于(标准输入上)fgets调用,服务器进程会被杀死.服务器TCP虽然正确的给客户TCP发送了一个FIN,但是既然客户进程正阻塞于从标准输入读入的过程,它将看不到这个EOF,直到从套接字读时为止(可能额已过了很长时间).这样的进程需要一种预先告知内核的能力,使得内核一旦发现进程指定的一个或多个I/O条件就绪(也就是说输入已准备好被读入,或者描述符已能承接更多的输出),它就通知进程.这个能力称为I/O复用,是由s

Unix网络编程 之 基本套接字调用(一)

       Unix/Linux支持伯克利风格的套接字编程,它同时支持面向连接和面向无连接类型的套接字.       套接字最常用的一些系统调用:       socket()             bind()       connect()       listen()       accept()       send()       recv()       sendto()       recvfrom()       close()       shutdown()       

Unix网络编程API

1.字节序函数 #include <netinet.h>uint16_t htons(uint16_t host16bitvalue);uint32_t htonl(uint32_t host32bitvalue); 返回:网络字节序值 uint16_t ntohs(uint16_t net16bitvalue);uint32_t ntohl(uint32_t net32bitvalue); 返回:主机字节序值 一个测试本机字节序的程序,可参见见unpv12e:intro/byteorder.

《UNIX网络编程 卷1:套接字联网API(第3版)》——2.6 TCP连接的建立和终止

2.6 TCP连接的建立和终止 为帮助大家理解connect.accept和close这3个函数并使用netstat程序调试TCP应用,我们必须了解TCP连接如何建立和终止,并掌握TCP的状态转换图. 2.6.1 三路握手建立一个TCP连接时会发生下述情形. (1)服务器必须准备好接受外来的连接.这通常通过调用socket.bind和listen这3个函数来完成,我们称之为被动打开(passive open). (2)客户通过调用connect发起主动打开(active open).这导致客户T

UNIX网络编程:UDP 中的外出接口的确定

已连接UDP套接字还可用来确定用于特定目的地的外出接口.这是由connect函数应用到UDP套接字时的一个副作用造成的:内核选择本地IP地址.这个本地IP地址通过为目的IP地址搜索路由表得到外出接口,然后选用该接口的主IP地址而选定. 注意:getsockname函数调用的位置. #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>

UNIX网络编程:UDP缺乏流量控制(改进版)

现在我们查看无任何流量控制的UDP对数据报传输的影响.首先我们把dg_cli函数修改为发送固定数目的数据报,并不再从标准输入读.如下,它写2000个1400字节大小的UDP数据报给服务器. 客户端程序cli.c: #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #inc