连接重置+ Java SE + TCP

时间:2012-08-05 21:48:49

标签: java tcp connection-reset

我正在开发Java Standard Edition应用程序 该应用程序的用户有一个假名。

我的应用程序可以用作服务器 在这种情况下,线程运行以接受来自应用程序的客户端实例的连接 当接受连接时,客户端用户被注册到列表中 服务器线程定期向每个客户端实例广播用户列表 客户端实例从服务器实例发送的数据更新其自己的用户列表。

我没有系统地解决问题 我认为我的问题与TCP协议有关 在测试期间,服务器和客户端实例在同一台计算机上运行 我已经使用RawCap和Wireshark捕获了在127.0.0.1发送和接收的数据帧。

以下是出现问题的方案:

  1. 用户U1将该应用程序作为服务器执行。

  2. 用户U2将应用程序作为客户端执行并连接到服务器实例。

  3. 服务器实例接受连接 我捕获了用于建立连接的帧 tns-adv表示客户端实例,tns-server表示服务器实例 这是框架:

    tns-adv> tns-server [SYN] Seq = 0
    tns-server> tns-adv [SYN,ACK] Seq = 0 Ack = 1
    tns-adv> tns-server [ACK] Seq = 1 Ack = 1

  4. 客户端实例将U2的假名发送到服务器实例 U2的笔名是“Moi” 假名之后是回车符和换行符 这是框架:

    tns-adv> tns-server [PSH,ACK] Seq = 1 Ack = 1 Len = 5

  5. 服务器实例接收U2的假名。 TCP确认会自动发送到客户端实例 这是框架:

    tns-server> tns-adv [ACK] Seq = 1 Ack = 6

  6. 服务器实例将U2注册到自己的用户列表中 U2在第二个位置注册 服务器将U2的位置(2)发送到客户端实例 该位置后面是回车符和换行符 这是框架:

    tns-server> tns-adv [PSH,ACK] Seq = 1,Ack = 6 Len = 3

  7. 客户端实例接收U2的位置,并在第二个位置将U2注册到自己的列表中 TCP确认将自动发送到服务器实例 这是框架:

    tns-adv> tns-server [ACK] Seq = 6 Ack = 4

  8. 服务器实例向客户端实例发送通知 该通知用于通知客户端实例发回数据,证明客户端实例仍然可用 通知是“[DISPO?]” 通知后面是回车符和换行符 这是框架:

    tns-server> tns-adv [PSH,ACK] Seq = 4 Ack = 6 Len = 11

  9. TCP确认将自动从客户端实例发送到服务器实例 但是客户端实例上的以下Java命令块:bufferedReader.readLine()
    该命令应该接收服务器通知 服务器实例捕获异常,其消息为:连接重置 我抓住了重置连接的框架 但我不知道为什么这个框架是从客户端实例发送的 这是框架:

    tns-adv> tns-server [RST,ACK] Seq = 6 Ack = 15

  10. 编辑:我已添加以下代码段以回应评论

    在客户端实例上的线程上执行的相关java命令

    // Connect to the server instance.
    socket = new Socket(adrIpv4, numPortSvr);
    
    // Instance an object to read data sent by the server instance.
    inputStream = socket.getInputStream();
    inputStreamReader = new InputStreamReader(inputStream);
    bufferedReader = new BufferedReader(inputStreamReader);
    
    // Instance an object to send data to the server instance.
    outputStream = socket.getOutputStream();
    outputStreamWriter = new OutputStreamWriter(outputStream);
    bufferedWriter = new BufferedWriter(outputStreamWriter);
    
    // Send my pseudonym to the server instance.
    // Frame sent : Frame 4.
    bufferedWriter.write(monJoueur.getPseudonyme());
    bufferedWriter.newLine();
    bufferedWriter.flush();
    
    // Wait for my position in the user list from the server instance.
    // Frame received : Frame 6.
    chaine = bufferedReader.readLine();
    
    // Register myself into this instance's user list at the position received from the server instance. 
    partie.setJoueurAtPosition(monJoueur, position);
    
    // Wait for an availability request from the server instance.
    // Frame expected : Frame 8.
    // That command blocks and the reset frame 9 is sent to the server instance.
    chaine = bufferedReader.readLine();
    

    在服务器实例上的线程上执行的相关java命令

    // Create the server socket.
    // Allocate automatically a free port number.
    socketServeur = new ServerSocket(0);
    partie.setSocketServeur(socketServeur);
    
    // Set the max time the server instance can wait for a connection from a client instance : 500 milliseconds.
    socketServeur.setSoTimeout(ThreadCreerPartie.DUREE_ATTENTE_CONNEX);
    
    // Wait 500ms max for a connection from a client instance.
    socket = socketServeur.accept();
    
    // Instance an object to read data sent by the client instance.
    inputStream = socket.getInputStream();
    inputStreamReader = new InputStreamReader(inputStream);
    bufferedReader = new BufferedReader(inputStreamReader);
    
    // Instance an object to send data to the client instance.
    outputStream = socket.getOutputStream();
    outputStreamWriter = new OutputStreamWriter(outputStream);
    bufferedWriter = new BufferedWriter(outputStreamWriter);
    
    // Wait for the client's pseudonym.
    // Frame received : Frame 4.
    chaine = bufferedReader.readLine();
    
    // Registrer the client into this instance's user list at the first available position.
    positionJoueur = partie.inscrireJoueur(socket, chaine);
    
    // Send the client's position in the user list to the client instance.
    // Frame sent : Frame 6.
    bufferedWriter.write(String.valueOf(positionJoueur));
    bufferedWriter.newLine();
    bufferedWriter.flush();
    
    // Send an availability request to the client instance.
    // Frame sent : Frame 8.
    bufferedWriter.write("[DISPO ?]");
    bufferedWriter.newLine();
    bufferedWriter.flush();
    
    // Receive the availability proof from the client instance.
    chaine = null;
    chaine = bufferedReader.readLine(); //< Raises an exception with the message : Connection reset.
    

1 个答案:

答案 0 :(得分:0)

[RST,ACK]会因为您的客户端不再侦听套接字而发生。代理可能已崩溃或超时并放弃连接。操作系统可能会为已经放弃的客户端发送RST ACK。