2016-11-17 60 views
0

当我运行我相当简单的TCP服务器时,我注意到第一次尝试连接并发送一个对象时出现连接重置错误。如果我保持服务器运行,但让客户端再次发送它一切正常。我在这里亏本,这是什么原因造成的?为什么我的连接在我尝试写入Socket时第一次复位?

客户:

 for (int i = 0; i < 3; i++) { 
     Socket s = new Socket("192.168.0.10", 9750); 
     SysIO.print("Connected: " + s.isConnected()); 
     ObjectOutputStream oos = new ObjectOutputStream(
      new BufferedOutputStream(s.getOutputStream())); 
     Object obj = new OneMessage("Hi there: " + i); 
     oos.writeObject(obj); 
     oos.flush(); 

     sleep(1000); // <-- turns error on and off :/ 
    } 

服务器:

try (ServerSocket incomingSocket = new ServerSocket(mPort)) { 
     SysIO.print("Game Server started..."); 
     incomingSocket.setSoTimeout(mTimeout); 

     while (mRunning) { 
      Socket clientConnection = null; 
      try { 
       clientConnection = incomingSocket.accept(); 
       clientConnection.setSoTimeout(3000); 

       final Socket connection = clientConnection; 
       Thread requestHandlingThread = new Thread(() -> { 
        mRequestHandler.handleRequest(connection); 
       }); 
       requestHandlingThread.start(); 

      } catch (SocketTimeoutException ste) { 
       SysIO.print("TCP timeout..."); 
      } catch (IOException ex) { 
       Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } catch (BindException ex) { 
     SysIO.print("Could not bind: " + ex.getMessage()); 
    } catch (IOException ex) { 
     SysIO.print("There was a problem with IO in TCP Server: " + ex.getMessage()); 
     Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex); 
    } 

请求处理程序:

public void handleRequest(Socket aRequest) { 

    try { 
     SysIO.print("Connected: " + aRequest.isConnected()); 
     ObjectInputStream ois = new ObjectInputStream(
      new BufferedInputStream(aRequest.getInputStream())); 
     GameMessage message = (GameMessage) ois.readObject(); 

     aRequest.close(); 


     SysIO.print("Received: " + message.getType()); 
    } catch (IOException | ClassNotFoundException ex) { 
     SysIO.print("IO exception: " + ex.getMessage()); 
     Logger.getLogger(SimpleHandler.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 

我试着关闭和从服务器的每个请求后未关闭套接字。

如果我运行客户端没有循环它似乎工作,我认为它在第一次失败,但我不能重新创建它。

如果我尝试在循环中运行客户端,所有连接将在第一次运行客户端时失败,但如果我重新启动客户端,则所有连接都将成功。

让睡眠(1000)暂停上述循环将使所有连接成功。这很简单,服务器无法处理快速连接尝试?我希望把请求处理放在单独的线程中可以实现这一点。但为什么循环中的第一个连接也会失败?

问候, 基督教

+1

对于读取超时,三秒钟是相当短的。至少应该有十个。您需要在循环结束时在客户端中使用'oos.close()'。 – EJP

+0

NB'isConnected()'在你测试的时候不可能是假的。 – EJP

回答

0

所以最后我eneded了这样的事情:

客户:

try { 
    Socket connection = new Socket(mHostAddress, mHostPort); 
    connection.setSoTimeout(mTimeOut); 
    ObjectOutputStream outgoing = new ObjectOutputStream(
      new BufferedOutputStream(connection.getOutputStream() 
      )); // <-- Opening output stream first in client (opposite to server) 
    outgoing.writeObject(mMessage); 
    outgoing.flush(); 
    outgoing.close(); // <-- closing the stream as per EJP's comment 
} catch (IOException ex) { 
    System.out.print("IOException in TCPSender: " + ex.getMessage()); 
} 

服务器:

ExecutorService pool = Executors.newFixedThreadPool(mClientThreads); 
try (ServerSocket server = new ServerSocket(mPort)) { 
    while (mRunning) { 
     final Socket client = server.accept(); 
     client.setSoTimeout(mTimeOut); 
     pool.execute(() -> { 
      mMessageHandler.handle(client); // mMessageHandler = NetworkMessageHandler 
     }); 
    } 
} catch (IOException ex) { 
    System.out.println("IO Exception occurred in TCPServer: " 
      + ex.getMessage()); 
} finally { 
    System.out.println("Server stopped..."); 
} 

NetworkMessageHandler

try { 
    ObjectInputStream input = new ObjectInputStream(
      new BufferedInputStream(aClient.getInputStream()) // Input first in server 
    ); 
    NetworkMessage message = (NetworkMessage) input.readObject(); 
    input.close(); // <-- closing stream 
    aClient.close(); // <-- making sure to close the Socket connection to client 

    act(message, sendersIP); <-- acting on the message from client 

} catch (IOException ex) { 
    System.out.println("An IO exception occurred " 
      + "in NetworkMessageHandler: " + ex.getMessage()); 
} catch (ClassNotFoundException ex) { 
    System.out.println("Could not recreate the sent class: " 
      + ex.getMessage()); 
} 

我确信我不会错过关闭我的流和套接字,并且遵循this oracle tutorial的某些提示提示。

Regards, Christian

+0

您需要首先在*至少一个对等端创建ObjectOutputStream。最好是两个,所以一个同伴不依赖于另一个。没有理由在两端采取相反的方式,它只是带来了不必要的风险。 – EJP

相关问题