问题
I'm trying to build a simple TCP multithreaded client/server application.
Whenever a Client (Socket
) connects to the ServerSocket
and send an Object
(Message
) that corresponds to the simple serializable class shown below, the server crashes when his ObjectInputStream
tries to read from the client Socket
getting a 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<String, Runnable> 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();
}
}
}
}
}
Debug output
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
What may be causing this exception ? I'm sure i do not close or reset the socket connection anywhere (client/server side).
EDIT:
Added client code below.
Client gets an exception when trying to receive()
a response from the server.
TCPService.java (Client)
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);
}
}
回答1:
Immediately upon sending a message, the client closes the ObjectOutputStream. This closes the socket's output stream, which closes the socket. By the time the client tries to read from the input stream, the socket is already closed, thus the exception on the client side. This may also be causing the problem on the server side, since by the time the server is reading data, the TCP connection may have been closed.
来源:https://stackoverflow.com/questions/33643652/socket-software-caused-connection-abort-recv-failed