tcp的关闭(shutdonw、close、SO_LINGER选项)与 连接断开情形判断

来源:互联网 发布:网络大电影盈利模式 编辑:程序博客网 时间:2024/05/01 16:48

1.close只是减少引用计数,只有当引用计数为0的时候,才发送fin,真正关闭连接

shutdown不同,只要以SHUT_WR/SHUT_RDWR方式调用即发送FIN包

2.对方关闭读,再对其写,写端会收到rst,再写收到sigpipe

3.SO_LINGER对shutdown无影响

4.监测各种tcp条件的方法

情形对端进程崩溃对端主机崩溃对端主机不可达本端tcp正动发数据对端tcp发送fin,通过可读返回0可监测到如果本端对其写,会收到rst,再写收到sigpipe本端tcp超时,套接字待处理错误设置为etimeout本端tcp超时,套接字待处理错误设置为ehostunreach本端tcp正主动接收数据对端发送fin,我们把它作为EOF读入 我们将停止接收数据,只是接收不到数据--没有其他症状我们将停止接收数据,只是接收不到数据--没有其他症状连接空闲,保持存活选项设置fin,可读,读的时候返回0 2小时后,发送9个存活探测,etimeout2小时后,发送9个存活探测,ehostunreach连接空闲,未设置保持存活fin,可读,读的时候返回0

转:http://blog.csdn.net/junjun150013652/article/details/38047851?utm_source=tuicool&utm_medium=referral

现在我们看看对于不同情况的close的返回情况和可能遇到的一些问题:


1.默认操作的close,close立即返回



说明:我们已经知道write操作返回成功只能说明数据已经发送到套接字的发送缓冲区,不能代表对端已经成功收到数据,close的默认返回成功也只是成功发出了一个FIN分节,也不代表对端已经确认


问题1:如果中途网络发生故障,很有可能服务端接收不到这个来自客户端的FIN分节;

问题2:假设服务器忙,那么来自客户端的数据由TCP加入到套接字接收缓冲区,下一个FIN分节也被加入到套接字接收缓冲区,然后等待处理,如果正好此时服务器应用进程崩溃掉,那么这些数据就丢失掉了,服务器并没有真正收到,而客户端也永远不会知道;


2.设置SO_LINGER套接字选项且l_linger为正值时的close:【数据ack了,并收到FIN了】 才返回



说明:这种情况下客户的close要到它的数据和FIN已经被服务器的TCP确认以后才会返回


问题:同上问题2


3.设置SO_LINGER套接字选项且l_linger为偏小正值时的close:时间到了 返回-1,EWOULDBLOCK错误



说明:在服务端的确认到达之前,SO_LINGER套接字选项设置的延滞时间到,close将会返回EWOULDBLOCK错误,且套接字发送缓冲区中的任何残留数据被丢弃。


问题:同问题2


总结:设置SO_LINGER套接字选项以后,close的成功返回只是告诉我们先前发送的数据的FIN已经由对端TCP确认,而不能告诉我们对端应用进程是否已经读取数据,如果不设置该套接字选项,那么我们连对端TCP是否确认了数据都不知道。


SO_LINGER套接字选项

struct linger {

     int l_onoff; /* 0 = off, nozero = on */

     int l_linger; /* linger time,POSIX specifies units as seconds */

};

l_onoff 非0,l_linger为0,丢弃发送缓冲区的任何数据,并发送rst给对端,没有四分组连接终止序列--没有fin,这样一来避免了TIME_WAIT状态,但是在2MSL秒内创建该连接的新化身,导致来自刚刚终止的连接上的旧数据被不正确的传送到新的化身上


让客户端知道服务器已读其数据的解决方法:

1.使用shutdown(设置SHUT_WR)+read



说明:调用写关闭的shutdown以后发送FIN分节,然后执行read,返回0则说明服务端已经读取数据然后发送终止连接的第三个分节(FIN分节)。


2.应用级确认,可由客户端和服务端指定一个终止协议

tcp本身不提供记录结束标志,tcp是一个字节流协议,没有任何记录边界:如果应用程序需要确定记录的边界,它就要自己去实现;



参考:

UNIX Network ProgrammingVolume 1, Third Edition: TheSockets Networking API


0 0