套接字 - 软件导致连接中止:recv失败 [英] Socket - Software caused connection abort: recv failed
问题描述
我正在尝试构建一个简单的TCP多线程客户端/服务器应用程序。
每当客户端( Socket
)连接到 ServerSocket
并发送对象时
(消息
)对应于下面显示的简单可序列化类,服务器在他的 ObjectInputStream $ c $时崩溃c>尝试从客户端读取
Socket
获取 SocketExpection
。
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();
}
}
}
}
}
调试输出
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).
下面添加了客户端代码。
尝试 receive()
来自服务器的响应时,客户端会收到异常。
Added client code below.
Client gets an exception when trying to receive()
a response from the server.
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。这将关闭套接字的输出流,从而关闭套接字。当客户端尝试从输入流中读取时,套接字已经关闭,因此客户端上的异常。这也可能导致服务器端出现问题,因为在服务器读取数据时,TCP连接可能已关闭。
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.
这篇关于套接字 - 软件导致连接中止:recv失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!