套接字 – 软件导致连接中止:recv失败

我正在尝试构建一个简单的TCPmultithreading客户端/服务器应用程序。 每当客户端( Socket )连接到ServerSocket并发送对应于下面所示的简单可序列化类的ObjectMessage )时,服务器在其ObjectInputStream尝试从客户端Socket读取SocketExpection时崩溃。

Message.java

 package storageserver; import java.io.Serializable; public class Message implements Serializable { private static final long serialVersionUID = 27015L; public int ClientStatus; // 0 - NotLogged ::: 1 - Logged public String Command; public String[] Commands; public Message() { this.ClientStatus = 0; this.Command = null; this.Commands = null; } public void createMessage(String msg) { this.Command = msg; this.Commands = msg.split("\\s+"); } } 

StorageServer.java

 package storageserver; // imports.. public class StorageServer { public static final int MAX_USERS = 250; ServerSocket myServerSocket; boolean serverOn = true; File workingDir; public StorageServer(int port, File dir) { try { InetAddress addr = InetAddress.getByName("192.168.1.73"); myServerSocket = new ServerSocket(port, MAX_USERS, addr); workingDir = dir; if(!workingDir.exists()) workingDir.mkdir(); System.out.println("StorageServer created successfully."); } catch (IOException ex) { Logger.getLogger(StorageServer.class.getName()).log(Level.SEVERE, null, ex); System.out.println("Could not create storage server on port 7000. Exiting."); System.exit(-1); } } public void listen() { System.out.println("Listening for connections..."); while(serverOn) { try { //accepts incoming TCP connection Socket clientSocket = myServerSocket.accept(); //starts new service thread to handle client requests in background new ClientHandleThread(clientSocket).start(); } catch (IOException e) { System.out.println("Exception encountered on accept. Ignoring. Stack Trace :"); e.printStackTrace(); } } try { myServerSocket.close(); } catch (IOException ex) { Logger.getLogger(StorageServer.class.getName()).log(Level.SEVERE, null, ex); } } class ClientHandleThread extends Thread { private Socket myClientSocket; private HashMap commandsMap; private Message messageToSend, messageToReceive; public ClientHandleThread() { super(); } public ClientHandleThread(Socket myClientSocket) { this.myClientSocket = myClientSocket; this.messageToSend = new Message(); this.messageToReceive = new Message(); } private void help() { messageToSend.createMessage("Avaible commands:\n\n" + "exit -> Exits the App\n" + "stop -> Stops the server\n" + "dir -> Gets personal file's info in current server\n"); messageToSend.ClientStatus = 0; } @Override public void run() { ObjectInputStream in = null; ObjectOutputStream out = null; System.out.println("Accepted connection from " + myClientSocket.getInetAddress().getHostAddress()+ ":" + myClientSocket.getPort()); try { System.out.println("IN.."); in = new ObjectInputStream(myClientSocket.getInputStream()); out = new ObjectOutputStream(myClientSocket.getOutputStream()); System.out.println("IN!"); messageToReceive = (Message) in.readObject(); //exception here - Software caused connection abort: recv failed System.out.println("Client Says :" + messageToReceive.Command); out.writeObject(messageToSend); out.flush(); } catch (IOException | ClassNotFoundException ex) { ex.printStackTrace(); Logger.getLogger(StorageServer.class.getName()).log(Level.SEVERE, null, ex); } finally { try { in.close(); out.close(); myClientSocket.close(); System.out.println("...Stopped"); } catch(IOException e) { e.printStackTrace(); } } } } } 

调试输出

 java.net.SocketException: Software caused connection abort: recv failed at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:170) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.net.SocketInputStream.read(SocketInputStream.java:223) at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2303) at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2596) at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2606) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1319) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at storageserver.StorageServer$ClientHandleThread.run(StorageServer.java:145) nov 11, 2015 2:53:36 AM storageserver.StorageServer$ClientHandleThread run 

可能导致此exception的原因是什么? 我确定我不会在任何地方(客户端/服务器端)关闭或重置套接字连接。

编辑:

在下面添加了客户端代 尝试从服务器receive()响应时,客户端会收到exception。

TCPService.java(客户端)

 package client; //imports.. public class TCPService { private Socket clientSocket; public TCPService(String host, int port) { try { clientSocket = new Socket(InetAddress.getByName(host), port); clientSocket.setSoTimeout(5000); } catch (IOException ex) { System.err.println("Cant connect to Storage Server.\n" + ex); System.exit(-1); } } public Message receive() { try { ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream()); try { Message msg = (Message) in.readObject(); if(msg instanceof Message) return msg; } catch (ClassNotFoundException e) { e.printStackTrace(); } } catch (IOException ex) { Logger.getLogger(TCPService.class.getName()).log(Level.SEVERE, null, ex); } return null; } public void send(Message msg) { try { ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream()); oos.writeObject(msg); oos.flush(); oos.close(); } catch (IOException ex) { Logger.getLogger(TCPService.class.getName()).log(Level.SEVERE, null, ex); } } //Main public static void main(String[] args) throws IOException { /* Service Variable Declaration */ TCPService tcpService = new TCPService(args[0], args[1]); /* Other Variables */ String buf = ""; Scanner scanIn = new Scanner(System.in); Message msg = new Message(); isTCPRunning = true; /* While-Loop for TCP Service */ while (isTCPRunning) { System.out.print("[User@StorageServer] Insert command: "); buf = scanIn.nextLine(); msg.createMessage(buf); scanIn.reset(); tcpService.send(msg); msg = tcpService.receive(); //SocketException -> Socket Closed System.out.println("[StorageServer] " + msg.Command); tcpService.handleMessage(msg); } } 

发送消息后,客户端立即关闭ObjectOutputStream。 这将关闭套接字的输出流,从而关闭套接字。 当客户端尝试从输入流中读取时,套接字已经关闭,因此客户端上的exception。 这也可能导致服务器端出现问题,因为在服务器读取数据时,TCP连接可能已经关闭。