套接字 - 软件导致连接中止:recv失败 [英] Socket - Software caused connection abort: recv failed

查看:406
本文介绍了套接字 - 软件导致连接中止:recv失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个简单的TCP多线程客户端/服务器应用程序。
每当客户端( Socket )连接到 ServerSocket 并发送对象时消息)对应于下面显示的简单可序列化类,服务器在他的 ObjectInputStream 尝试从客户端读取 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆