`
shx
  • 浏览: 30876 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

socket关闭的问题

阅读更多
以前发在公司内网的文章,发出来共享,隐去具体项目、人员的名字。

某天检查某位同事遇到的tcp一端关闭另一端读数据报connect reset异常,问题现象是:windows部署客户端,linux上部署服务端的情况下执行操作客户端经常会报connection reset错误。

一、问题定位
第一步抓包分析,发现RST包。

第二步查tcp协议规范和java实现:
tcp常见的关闭方式通常是四次握手(很少的情况下是三次),发送两个FIN segment,两个ACK segment,参见RFC 793《TRANSMISSION CONTROL PROTOCOL》

  TCP A                                 TCP B

1. ESTABLISHED                             ESTABLISHED

2. (Close)
    FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> --> CLOSE-WAIT

3. FIN-WAIT-2 <-- <SEQ=300><ACK=101><CTL=ACK>     <-- CLOSE-WAIT

4.                                     (Close)
    TIME-WAIT   <-- <SEQ=300><ACK=101><CTL=FIN,ACK> <-- LAST-ACK

5. TIME-WAIT   --> <SEQ=101><ACK=301><CTL=ACK>     --> CLOSED

6. (2 MSL)
    CLOSED                                    

                Normal Close Sequence
                             
               
TCP的协议里关闭动作意味着"我没有数据需要发送了",当我这端关闭时,我还可以接收数据,直到对方端也关闭。
RFC1122《Requirements for Internet Hosts -- Communication Layers》描述了"half-duplex" 关闭方式,即当我这端关闭时既不能读数据也不能写数据。
一般情况下这种关闭方式的网络交互方式同一,但当我这端还有数据没读的情况下会发送RST segment给对方,告诉对方你发过来的数据丢失了,不幸的是,对方的操作系统不能把这个和网络连接的RST区分开(测试情况要好一些,windows可以区分windows的,linux可以区分linux和windows的)           
java里的Socket close方法在windows、linux平台上都使用的是"half-duplex" 关闭方式。

第三步检查代码,发现出问题的程序服务端的确存在有数据没读的情况,又使用了Socket close方法,所以某些情况下就会触发客户端报connection reset的错误。

二、修改办法:
1.将Socket close方法换成shutdownOutput,将不会使用"half-duplex" 关闭方式,或者
2.在Socket close之前,加上
                  while (true) {                      
                      if (dis.read() == -1) {
                            break;
                      }
                  }
                  确定对方已经关闭后再关闭(隐含把未读的数据也读了)。
个人觉得第二种改法更符合逻辑,应用层的功能不应该依赖底层协议的细节。              
程序中最初是按第一种改法改的,后来就没动,倒也没想到什么实际的问题。    

三、另外要注意的问题
关闭socket的InputStream,OutputStream时要谨慎,它们会调用Socket的关闭方法。
分享到:
评论
4 楼 CapsLk 2009-11-25  
                 while (true) {                       
                      if (dis.read() == -1) { 
                            break; 
                      } 
                  } 

代码中dis指的什么?
顺便再问个问题:我要做拒绝某些IP连接到socket服务端,用java的socket能够在客服端尝试连接到服务端的时候,服务端拒绝连接使之不能建立tcp连接?
我认为我下面的代码没有达到我想要的要求
	Socket socket = serverSocket.accept();
	String ip = socket.getInetAddress().getHostAddress();
	if("127.0.0.1".equals(ip)){
		socket.close();
	}
3 楼 only_java 2009-09-16  
神啊,我说我关闭个stream怎么会把socket连接也关了。。。。。。这下明白了
2 楼 shx 2009-06-17  
不用客气,能帮到你很高兴。
1 楼 major361 2008-12-02  
得此文
我问题终于解决了

关闭socket的InputStream,OutputStream时要谨慎,它们会调用Socket的关闭方法。

将Socket close方法换成shutdownOutput,将不会使用"half-duplex" 关闭方式

十分感谢博主!

相关推荐

    socket server关闭时导致socket client也关闭 的原因及解决办法

    当Socket Server(服务端)关闭时,通常会导致与之相连的Socket Client(客户端)也关闭,这是因为TCP连接是全双工的,即数据可以双向传输。当一方关闭连接,另一方在尝试发送或接收数据时会检测到连接已断开,从而...

    对一个对端已经关闭的socket调用两次write, 第二次将会生成SIGPIPE信号, 该信号默认结束进程.zip

    当我们处理TCP连接时,必须了解如何正确地管理和关闭Socket,因为不恰当的操作可能导致一些异常情况,例如标题中提到的问题:“对一个对端已经关闭的socket调用两次write, 第二次将会生成SIGPIPE信号, 该信号默认...

    socket客户端

    此外,`Socket`类还提供了其他方法,如`Shutdown`用于关闭发送或接收功能,`Close`用于关闭套接字,以及`Dispose`用于释放资源。为了保持良好的编程实践,应当在不再需要Socket对象时正确关闭和清理资源。 在实际...

    HPSocket.Net-develop_hpsocket.net_HPSocket_.net_socket_tcp_

    5. 关闭连接:`socket.Shutdown(SocketShutdown.Both); socket.Close();` 【标签】"hpsocket.net HPSocket .net socket tcp"暗示了HPSocket.Net可能是一个扩展了.NET Framework的Socket功能的库,提供了更高级别的...

    socket池,socket

    为了解决这个问题,引入了Socket池(或Socket连接池)。Socket池是一种管理机制,它维护着一组预先创建的、可重用的Socket连接。当应用程序需要建立新的网络连接时,不是直接创建新的Socket,而是从池中获取已经存在...

    HP-Socket5.3.2

    HP-Socket是一套通用的高性能TCP/UDP/HTTP 通信框架,包含服务端...HP-Socket对通信层完全封装,应用程序不必关注通信层的任何细节;HP-Socket提供基于事件通知模型的API接口,能非常简单高效地整合到新旧应用程序中

    判断Socket是否断开的小代码

    4. **Socket关闭**: - 当检测到连接异常或不再需要连接时,及时关闭Socket连接是非常重要的一步。 通过上述分析,我们可以了解到如何通过简单的代码实现Socket连接状态的监控以及数据的正确接收处理,这对于开发...

    IOCP服务器端框架,用于实现高并发服务器

    比较好的解决了掉线,死机,超时等socket关闭问题及WAIT_TIME问题。同时用较好方式实现了AcceptContext,ReceiveContext,Sendcontext的管理(自己写了个static类),重用各种context,避免频繁的new与delete操作.系统...

    c#socket断开重连

    本文将详细讲解如何在C#中处理Socket的断开重连问题,以及如何实现循环接收数据。 Socket是网络通信的基础组件,它提供了一种进程间通信(IPC)的方式,允许两个网络上的应用程序进行双向数据交换。在C#中,我们...

    SuperSocket Socket C# 通讯详细介绍

    **SuperSocket Socket C# 通讯详解** 在C#编程领域,网络通信是一个不可或缺的部分,而SuperSocket则是一个强大且易用的.NET Socket服务器框架。它为开发者提供了构建自定义网络应用服务的基础,使得处理TCP连接变...

    Socket的问题.doc

    其方法是在连接事件中发送数据,并在`OnRead`事件中让Socket关闭,同时通过一个计数器来控制发送的次数,之后再重新打开Socket。然而,在实际操作过程中,作者发现了一个奇怪的现象:当程序运行时,如果用户切换到...

    socketTool socket 调试 助手

    - 关闭连接:完成通信后,调用close()函数关闭Socket。 5. **调试技巧**: - 使用SocketTool的服务器模式检查客户端是否正确发送数据,以及服务器是否正确接收。 - 切换到客户端模式,验证服务器是否正确响应,...

    socket客户端_socket_

    Socket编程中,网络异常如连接失败、数据传输错误等是常见的问题,因此需要编写适当的异常处理代码,确保程序的健壮性。 8. **多线程/异步IO**: 对于高并发的网络应用,客户端可能需要同时处理多个Socket连接。...

    SocketTool,Socket调试工具,TCP、UDP编程必备

    在实际开发中,SocketTool可以帮助我们检查以下问题: - 数据是否正确发送和接收。 - TCP连接是否成功建立和关闭。 - UDP数据包是否到达目标,丢包情况如何。 - 网络延迟和带宽限制对通信的影响。 此外,SocketTool...

    SocketTool

    4. 关闭连接:完成通信后,双方都需调用`close()`方法关闭Socket,释放资源。 SocketTool作为一款测试工具,其功能可能包括: 1. 客户端模拟:允许用户输入目标IP地址和端口号,模拟TCP或UDP连接,发送自定义的...

    Socket编程例子

    3. 关闭连接:完成通信后,客户端和服务器都需要调用`close()`函数关闭Socket,释放资源。 三、UDP Socket编程 UDP Socket编程相比TCP更简单,因为它不需要建立和维护连接。客户端和服务器都使用`socket()`创建...

    socket错误代码对应表

    - **Socket error #10058 - Cannot send after socket shutdown**:Socket关闭后不能发送数据。 - **Socket error #10061 - Connection refused**:连接被拒绝。 - **Socket error #10064 - Host is down**:主机已...

    Socket模拟服务器_Socket模拟服务器_

    为了防止资源泄露,服务器在完成通信后需要关闭Socket和相关的流对象。 ```java writer.close(); outputStream.close(); clientSocket.close(); serverSocket.close(); ``` **6. 多线程处理** 在实际应用中,服务器...

    VB6.0 简单 Socket 服务端

    不过,实际应用中可能还需要考虑多线程处理多个客户端连接、数据的编码解码、异常处理等问题,这些都需要根据具体需求进行扩展和优化。 总之,VB6.0通过Winsock控件为开发者提供了一种直观且易于使用的途径,来实现...

    matlab环境下socket通信

    4. **关闭连接**:完成通信后,使用`fclose`函数关闭Socket连接。 ```matlab fclose(s); ``` 5. **错误处理**:在整个过程中,需要捕获并处理可能出现的错误,例如连接失败、数据传输错误等。 在MATLAB中,`...

Global site tag (gtag.js) - Google Analytics