有的时候客户端批量发送数据,发送完数据后,如果直接调用close(假设引用计数为0)
则发送端与接收端均被关闭。但可能管道中还有数据在传输,这时管道中对方的ack,以及fin的确认
就不能收到了,连接就不是正常关闭。
close函数把描述符的引用计数减一,仅仅在该计数变为0的时候,才真正的关闭套接字,而使用
shutdown函数可以不管引用计数就激发了TCP的正常连接终止序列;
close函数终止读和写两个方向的数据传输。既然TCP连接是全双工的,有时候我们需要告知对端我们已
经完成了数据发送,我们仅仅需要关闭数据发送的一个通道,但是我们还是可以接收到对端发送过来的
数据,这种控制只有利用shutdown函数才能实现。
1>.如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程
都调用了close,套接字将被释放。
2>. 在多进程中如果一个进程中shutdown(sfd,SHUT_RDWR)后其它的进程将无法进行通信. 如果一个
进程close(sfd)将不会影响到其它进程.
SO_DEBUG:本选项仅由TCP支持,当给一个TCP套接字开启此选项时,内核将为TCP在该套接字发送和
接受的所有分组保留详细跟踪信息
SO_ERROR:当一个套接字发生错误,源于BSD的内核中的协议模块将该套接字的名为so_error的变量设为标准的Unix
Exxx值中的一个,我们称它为该套接字的待处理错误。内核能够以以下两种方式通知进程这个错误:
1> 如果进程阻塞在对套接字的select调用上,那么无论检查可读条件还是可写条件,select均返回并设置
其中一或2个条件。
2> 如果进程使用信号驱动式I/O模型。那就给进程或进程组产生一个SIGIO信号。
SO_KEEPALIVE:设置该选项后,如果两小时内在该套接字的任一方向上都没数据
交换,TCP就自动给对端发送一个保持存活探测分节。这是一个对端必须响应的分节,
他会导致以下三种情况
1> 对端以期望的ACK响应。应用进程得不到通知(因为一切正常)。再又经过仍无动静的
2小时后,TCP将发出另一个探测分节
2> 对端以RST响应,它告知本段TCP,对端已经崩溃并重启。该套接字的待处理错误被置为
ECONNRESET,套接字本身则被关闭
3> 对端保持存活探测分节没有任何响应。源自BSD的TCP将另外发送8个探测分节。最后还得不
到响应的话就放弃。
SO_LINGER:
情形 | 对端进程崩溃 | 对端主机崩溃 | 对端主机不可达 |
本端TCP正主动发送数据 | 对端TCP发送一个FIN分节, 这通过使用select判断可读条件 立即能检测出来。如果本端TCP 发送另外一个分节。对端TCP就以 RST响应。如果在本端接受到RST 后禁用进程仍尝试写套接字。我们的 套接字实现就给进程发送一个SIGPIPE 信号 | 本端TCP将超时,且该套待 处理错误被置ETIMEDOUT | 本端TCP将超时,且该套接字的待 处理错误被置为EHOSTUNREACH |
本端TCP正主动接收数据 | 对端TCP将发送一个FIN,我们将把它 作为一个(可能是过早的)EOF读入 | 我们将停止接受数据 | 我们将停止接受数据 |
连接空闲,保持存活选项 (SO_KEEPALIVE)以设置 | 对端TCP发送一个FIN分节, 这通过使用select判断可读条件 立即能检测出来。 | 在毫无动静2小时后, 发送9个保持存活探测 分节。然后用套接字的 待处理错误被设置为 ETIMRDOUT | 在毫无动静2小时后, 发送9个保持存活探测 分节。然后用套接字的 待处理错误被设置为 EHOSTUNREACH |
连接空闲,保持存活选项 (SO_KEEPALIVE)以设置 | 对端TCP发送一个FIN分节, 这通过使用select判断可读条件 立即能检测出来。 | 无 | 无 |
int l_onoff;
int l_linger;
};
函数 | 说明 |
shutdown.SHUT_RD | 在套接字上不能再接受请求。进程仍可向套接字中发送数据。接受缓冲区数据被丢弃。再接收到的任何 数据都被丢弃。对套接字发送缓冲区没有影响 |
shutdown,SHUT_WR | 在套接字上不能再发送请求。进程仍可接收数据。发送缓冲区中的剩余数据将被发送 ,后跟FIN终止序列 |
close,l_onoff=0 (默认情况) | 在套接字上不能再接受或发送数据。套接字发送缓冲区中的内容被发送到对端。接受缓冲区的内容被丢弃。 如果描述符的引用计数=0,那么发送完数据后,跟以FIN终止序列 |
close,l_onoff=1 l_linger=0 | 在套接字上不能再接受或发送数据。如果描述符的引用计数=0,RST被发送给对端。连接的状态置为 CLOSED(没有TIME_WAIT状态)。套接字发送缓冲区和套接字接受缓冲区都被丢弃 |
close,l_linger=1 l_linget !=0 | 在套接字上不能再接受或发送数据。发送缓冲区中的剩余数据将被发送 ,如果描述符的引用计数=0,在发送完发送缓冲区的数据后,跟以FIN终止序列。接受缓冲区的数据被丢弃。如果连接变为CLOSED状态前延滞 时间到,则返回E_WOULDBLOCK错误 |