网络编程Socket之TCP之close/shutdown详解(续)

接着上一篇网络编程Socket之TCP之close/shutdown详解

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

1.默认操作的close

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

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

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

2.设置SO_LINGER套接字选项且l_linger为正值时的close

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

问题:同上问题2

3.设置SO_LINGER套接字选项且l_linger为偏小正值时的close

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

问题:同问题2

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

解决方法:

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

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

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

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

参考:

《UNIX Network ProgrammingVolume 1, Third Edition: TheSockets Networking API》

时间: 2024-10-19 07:09:21

网络编程Socket之TCP之close/shutdown详解(续)的相关文章

网络编程Socket之TCP之close/shutdown详解

close: 当套接字的引用计数为0的时候才会引发TCP的四分组连接终止序列: shutdown: 不用管套接字的引用计数就激发TCP的正常连接终止序列: 这里由一个SO_LINGER套接字选项 struct linger { int l_onoff; /* 0 = off, nozero = on */ int l_linger; /* linger time,POSIX specifies units as seconds */ }; shutdown:SHUT_RD 关闭连接的读这一半,进

网络编程Socket之TCP之TIME_WAIT状态详解

下面我们用最简单的一对一的客户服务器模型来重现编程中遇到的一些问题: 初学socket的时候在编写socket程序的时候会遇到很多莫名其妙的问题,比如说bind函数返回的常见错误是EADDRINUSE 使用下面的程序重现这个状态: client: int main(int argc, const char * argv[]) { struct sockaddr_in serverAdd; bzero(&serverAdd, sizeof(serverAdd)); serverAdd.sin_fa

java网络编程socket\server\TCP笔记(转)

java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04|  分类: Socket |  标签:java  |举报|字号 订阅 1 TCP的开销 a  连接协商三次握手,c->syn->s,s->syn ack->c, c->ack->s b  关闭协商四次握手,c->fin->s, s->ack-c,s->fin->c,c->ack->s c  保持数据有序,响应确认等计算开销 d

iOS开发——网络编程Swift篇&(八)SwiftyJSON详解

SwiftyJSON详解 最近看了一些网络请求的例子,发现Swift在解析JSON数据时特别别扭,总是要写一大堆的downcast(as?)和可选(Optional),看?号都看花了.随后发现了这个库SwiftyJSON,问题迎刃而解,灰常优雅和Swifty! 简单介绍下这个库(内容译自SwiftyJSON的README): 为什么典型的在Swift中处理JSON的方法不好? Swift语言是一种严格的类型安全语言,它要求我们显示的设置类型,并帮助我们写出更少bug的代码.但是当处理JSON这种

网络编程Socket它TCP它TIME_WAIT国家具体解释

下面我们用最简单的一对一的客户server编程模型重现遇到的一些问题: 初学者socket当写作socket名其妙的问题.比方说bind函数返回的常见错误是EADDRINUSE 使用以下的程序重现这个状态: client: int main(int argc, const char * argv[]) { struct sockaddr_in serverAdd; bzero(&serverAdd, sizeof(serverAdd)); serverAdd.sin_family = AF_IN

网络编程Socket之TCP之connect详解

对TCP套接字调用connect会激发三次握手,如下: 客户端是主动打开连接的一端,会发送第一个SYN分节,然后等待确认,此时连接状态为SYN_SENT,当收到服务端的确认后连接建立,状态变为ESTABLISHED: 服务器是被动打开连接的一端,调用listen导致套接字从CLOSED状态变为LISTEN状态,当收到来自客户端的SYN分节以后状态变为SYN_RCVD,然后发送第二个SYN分节,等待客户端的确认,收到客户端的确认以后连接建立,状态变为ESTABLISHED: 三次握手中的两个SYN

二、网络编程-socket之TCP协议开发客户端和服务端通信

知识点:之前讲的udp协议传输数据是不安全的,不可靠不稳定的,tcp协议传输数据安全可靠,因为它们的通讯机制是不一样的.udp是用户数据报传输,也就是直接丢一个数据包给另外一个程序,就好比寄信给别人,信丢了你也不知道,tcp传输需要先和服务端建立连接,当客户端与服务器连接时,服务器会给出应答,我俩连上了,而且数据传过来还会进行一个数据包数量验证,不一致会重新发送,还有其他种种验证,总之保证了数据传输安全可靠   这一章主要介绍使用套接字,编写一个tcp协议客户端和服务端.同样要用到上一章节提到小

网络编程Socket之TCP之read/write

从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不代表对端TCP或应用进程已接收到数据. 对端TCP必须确认收到的数据,伴随来自对端的ACK的不断到达,本端TCP至此才能从套接字发送缓冲区中丢弃已确认的数据,TCP必须为已发送的数据保留一个副本,直到它被对端确认为止. UDP不保存应用进程数据的副本因此无需一个真正的发送缓冲区,write调用成功返回表示所写的数据报或其所有分片已被加入数据链路层的输出队列. 对于read调用(套接字标志为阻塞),如果接

网络编程Socket之TCP之select概述

I/O模型: 1.  阻塞式I/O模型 2.  非阻塞式I/O模型:使用fcntl将套接字设置成非阻塞:然后轮询读取数据,这样会耗费大量CPU时间: 3.  I/O复用模型:阻塞在select上: 4.  信号驱动式I/O模型: 5.  异步I/O模型:aio_read,信号直到数据已复制到应用进程缓冲区才产生 select: select的最后一个时间参数: 1.  为空时表示永远等下去: 2.  为具体非0时间时表示不超过该时间返回: 3.  结构体中秒和微秒都为0表示不等待,即轮询: se