Tcp 断开连接(重要)

这篇还不错的文章
TCP状态转移要点
    TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。网络服务器程序要同时管理大量连接,所以很有必要保证无用连接完全断开,否则大量僵死的连接会浪费许多服务器资源。在众多TCP状态中,最值得注意的状态有两个:CLOSE_WAIT和TIME_WAIT。
1、LISTENING状态
  FTP服务启动后首先处于侦听(LISTENING)状态。
2、ESTABLISHED状态
  ESTABLISHED的意思是建立连接。表示两台机器正在通信。
3、CLOSE_WAIT
    对方主动关闭连接或者网络异常导致连接中断,这时我方的状态会变成CLOSE_WAIT 此时我方要调用close()来使得连接正确关闭
4、TIME_WAIT
    我方主动调用close()断开连接,收到对方确认后状态变为TIME_WAIT。TCP协议规定TIME_WAIT状态会一直持续2MSL(即两倍的分段最大生存期),以此来确保旧的连接状态不会对新连接产生影响。处于TIME_WAIT状态的连接占用的资源不会被内核释放,所以作为服务器,在可能的情况下,尽量不要主动断开连接,以减少TIME_WAIT状态造成的资源浪费。
    目前有一种避免TIME_WAIT资源浪费的方法,就是关闭socket的LINGER选项。但这种做法是TCP协议不推荐使用的,在某些情况下这个操作可能会带来错误。
 
 
 
在连接撤销过程中,有如下四个过程:   

1.         HOST1上的应用程序关闭己方的连接导致TCP发送一个FIN消息给HOST2。
2.         HOST2发送一个确认消息给HOST1,并且HOST2把FIN作为EOF递交给HOST2上的应用程序。
3.         一段时间过后,HOST2上的应用程序关闭它那边的连接,引发一个FIN消息给HOST1。
4.         HOST1给HOST2发送一个确认消息,然后HOST2关闭连接并释放资源,然而,HOST1却没有关闭连接,而是进入了TIME_WAIT状态,并为两个最大段生存时间(2MSL)保留在此状态.

为什么需要time_wait?
1.       因为在第四步的时候,HOST1发送的ACK可能丢失并导致HOST2重新发送FIN消息,TIME_WAIT维护连接状态.
       如果执行主动关闭的一方HOST1 不进入到TIME_WAIT状态就关闭连接那会发生什么呢?当重传的FIN消息到达时,因为TCP已经不再有连接的信息了,所以就用RST(重新启动)消息应答,导致HOST2进入错误的状态而不是有序终止状态,如果发送最后ACK消息的一方处于TIME_WAIT状态并仍然记录着连接的信息,它就可以正确的响应对等方HOST2的FIN消息了.
2.       TIME_WAIT为连接中”离群的段”提供从网络中消失的时间.
         考虑一下,如果延迟或者重传段在连接关闭后到达时会发生什么呢?通常情况下,因为TCP仅仅丢弃该数据并响应RST消息,所以这不会造成任何问题。当RST消息到达发出延时段的主机时,因为该主机也没有记录连接的任何信息,所以它也丢弃该段。然而,如果两个相同主机之间又建立了一个具有相同端口号的新连接,那么离群的段就可能被看成是新连接的,如果离群的段中数据的任何序列号恰恰在新连接的当前接收窗口中,数据就会被重新接收,其结果就是破坏新连接。

 
 
 
 
一、TCP连接关闭的几种方式:
1、“正常”关闭:调用close()关闭socket、没close但进程正常结束(当然这是不应该的做法)、进程core掉、在shell命令行中kill掉进程,都可抽象成“正常”关闭。因为即使core掉,内核也会马上帮应用程序回收(close)socket文件描述符。
     “正常”关闭,默认情况下(非默认即设置Linger下面会介绍),关闭端即客户端TCP层会发FIN包,对端即服务器TCP层收到后,回ACK,客户端进入FIN_WAIT2状态。此时,TCP终止连接的4个分组中服务器应该发的第3个分组FIN包,其TCP层是不会主动发的,只有服务器端socket“正常”关闭,才会发出这个FIN包。至此,客户端进入TIME_WAIT状态。
2、“非”正常关闭:客户端崩溃了,此时肯定发不出FIN包了(当然啦,内核都没机会帮应用程序回收资源了)。这种情况,服务器端有如下两种情况:
    A、服务器send数据,因为客户端已经崩溃,服务器收不到ACK自然会不停的重传。源自
        Berkeley的重传机制,重传8次,相对第一次传的15分钟后仍没收到ACK,则返回
        ETIMEDOUT或EHOSTUNREAC错误。如果服务器不理会这个错误,再次调用send,则
        立马返回Broken Pipe错误。    
       注:15分钟超时可以在 /proc/sys/net/ipv4/tcp_retries2 中修改
   B、 服务器不发任何数据了,那只有靠应用层心跳检测机制或Keepalive,来发觉TCP断连了。
二、SO_LINGER套接口选项
           A、l_onoff设置为0,这也是默认情况,函数close()是立即返回的,然后TCP连接双方是通过
                FIN、ACK4分组来终止TCP连接的。当然,发送缓冲区还有数据的话,系统将试着将这些数据
                发送到对方。
           B、l_onoff非0,l_linger设置0,函数close()立即返回,并发送RST终止连接,发送缓冲区的数据丢弃。
           C、l_onoff非0,l_linger非0,函数close()不立即返回,而是在(a)发送缓冲区数据发送完并得到确认
                 (b)l_linger延迟时间到,l_linger时间单位为微妙。两者之一成立时返回。如果在发送缓冲区数据发送
                完并被确认前延迟时间到的话,close返回EWOULDBLOCK(或EAGAIN)错误。
三、客户端TCP连接“正常”关闭,服务器的几种情况:
          情形 客户端l_onoff设置为0, 
“正常”关闭 客户端l_onoff非0,l_linger设置0,“正常”关闭 
服务器阻塞模式send,正阻塞在send函数未返回 客户端TCP发送FIN,服务器send函数返回成功(返回字节数是实际拷贝到发送缓冲区的字节数)。客户端发送RST。如果服务器再次调用send,将返回errno[32]:Broken pipe 客户端TCP发送RST,服务器函数返回成功(返回字节数是实际拷贝到发送缓冲区的字节数)。若服务器再次调用send,则返回-1,errno[104]:Connection reset by peer。若再次调用send,则返回-1,errno[32]:Broken pipe 
服务器空闲 客户端TCP发送FIN,若服务器没理会而调用send,客户端发送RST,send返回-1,errno[32]:Broken pipe 客户端TCP发送RST,若服务器没理会而调用send,send返回-1,errno[104]:Connection reset by peer。若再次调用send,则返回-1,errno[32]:Broken pipe
总之,1、收到对端RST后,仍然调入send(),则返回Connection reset by peer,再次调用send(),则返回Broken pipe
         2、收到对端FIN后,仍然调研哪个send(),直接返回Broken pipe
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
在编写一个WinCE TCP服务器时,保持连接通常是非常重要的。以下是一些步骤来实现这一点: 1. 创建一个TCP监听套接字。使用`socket`函数创建一个套接字,并调用`bind`函数将其绑定到一个特定的IP地址和端口号上。然后使用`listen`函数开始监听连接请求。 2. 使用循环来接受连接。使用`accept`函数接受客户端的连接请求,并创建一个新的套接字来与客户端进行通信。这样可以同时与多个客户端进行通信。 3. 在与客户端建立连接后,使用循环维持通信。可以使用`recv`函数从客户端接收数据,并使用`send`函数向客户端发送数据。循环直到客户端关闭连接或者发生错误。 4. 如果客户端关闭了连接,要关闭与该客户端的套接字。在每次循环迭代的末尾,可以使用`closesocket`函数关闭与客户端之间的套接字。 5. 如果需要保持持久连接,可以在循环中添加一些额外的逻辑。例如可以设置一个超时计时器,如果在一定时间内未收到客户端发送的数据,则关闭与该客户端的连接。也可以建立一个心跳机制,定期向客户端发送心跳信号,以确保连接仍然有效。 6. 要注意处理异常情况。例如,如果套接字发生错误或者断开连接,则需要及时关闭套接字,并在服务器端打印相应的错误信息。 综上所述,以上是保持WinCE TCP服务器连接的一些关键步骤。通过适当的循环和处理异常情况,可以确保服务器能够持续与客户端进行通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值