Java服务器-客户端连接重置

时间:2018-11-20 14:50:33

标签: java server connection client file-transfer

我在本地计算机上运行服务器和客户端应用程序。 客户端获取文件,将其更改并发送到服务器,然后服务器响应该文件是否正确。客户端执行多次,一次发送一个文件。 我从客户端发送了两个文件,在第二个文件上,我得到了连接重置

服务器摘要:

private void initServer() throws IOException {
    while (true) {
        ServerSocket server = new ServerSocket(55555);
        Socket fromclient = server.accept();

        InputStream sin = fromclient.getInputStream();
        OutputStream sout = fromclient.getOutputStream();

        DataInputStream in = new DataInputStream(sin);
        DataOutputStream out = new DataOutputStream(sout);

        String line = in.readUTF();

        if (line.equals("new file")) {
            long fileSize = in.readLong();

            tempSavedFile = new File("/home/evgeniy/Files/Downloads/temp");

            tempSavedFile.createNewFile();
            try (FileOutputStream fos = new FileOutputStream(tempSavedFile)) {
                int t;
                for (int i = 0; i < fileSize; i++) {
                    t = sin.read();
                    fos.write(t);
                }
            }

            if (checkPadding(tempSavedFile)) {
                out.writeInt(PADDING_OK_RESPONSE);
            } else {
                out.writeInt(PADDING_ERROR_RESPONSE);
            }
            out.flush();
        }
        out.close();
        in.close();
        sout.close();
        sin.close();
        fromclient.close();
        server.close();
    }
}

在for循环中调用新线程的客户端类

for (byte i = 0; i < 2; i++) {
Callable callable = new FileSender(tempFile);
        FutureTask<Integer> ftask = new FutureTask<>(callable);
        Thread thread = new Thread(ftask);            
        thread.start();

        int response = 3244;
        try {
            response = ftask.get();
        } catch (InterruptedException | ExecutionException ex) {
            Logger.getLogger(FXMLController.class.getName()).log(Level.SEVERE, null, ex);
        }
        putMessage(String.valueOf(response));

客户端可调用线程:

public Integer call() throws Exception {
    Socket socket = new Socket(address, serverPort);
    InputStream sin = socket.getInputStream();
    OutputStream sout = socket.getOutputStream();
    DataInputStream in = new DataInputStream(sin);
    DataOutputStream out = new DataOutputStream(sout);

    out.writeUTF("new file");
    out.flush();

    out.writeLong(file.length);
    out.flush();

    sout.write(file);
    sout.flush();

    System.out.println(socket.isConnected());
    int response = in.readInt();
    System.out.println("--------RESP="+response);

    out.close();
    in.close();
    sin.close();
    sout.close();
    socket.close();
    return response;
}

如您所见,我发送了两个文件,并在客户端应用程序上获得此控制台输出:

true
--------RESP=200
true
ноя 20, 2018 5:16:36 PM com.evgeniy_mh.paddingoracle.FXMLController SendFileToServer
SEVERE: null
java.util.concurrent.ExecutionException: java.net.SocketException: Connection reset

另外,我不明白为什么套接字可以,但是

int response = in.readInt();

引发连接重置异常。

1 个答案:

答案 0 :(得分:0)

您的代码创建一个新的ServerSocket,然后为它处理的每个请求关闭创建的服务器套接字。该代码不使用相同的ServerSocket实例来服务多个请求。


连接重置失败似乎是由于这个原因,因为当第二个请求与服务器建立套接字连接时,现有的ServerSocket被关闭并在通向该端口的同一端口上重新创建。连接被重置。首先,请尝试在while循环之外进行ServerSocket创建。

private void initServer() {
    try (ServerSocket server = new ServerSocket(5555)) {
        while (true) {
            Socket fromclient = server.accept();

        ... // remaining code

            fromclient.close();
        }
    } catch (IOException ioe) {
        // handle failures
    }
}

try-with-resources处理.close()服务器套接字上的AutoCloseable调用。


另外,请注意,请求将在代码中的单个线程上顺序处理。通常,与从Socket(或从其派生的流)的连接中获得的ServerSocket#accept()会传递到单独的线程进行处理,这与您的代码以串行方式处理请求不同。