我遇到了一个java.net.SocketException: Connection reset错误。

3
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

public class Server {
    // ArrayList<PrintWriter> writers; // hold a list of current connections
    Set<Socket> sockets = new HashSet<Socket>();
    private ServerSocket serverSocket;
    private Socket sock;
    private static SimpleDateFormat date = new SimpleDateFormat(
            "dd/mm/yyyy hh:mm:ss");
    private static Calendar cal = Calendar.getInstance();

    public static void main(String[] args) {
        new Server().go();
    }

    public void go() {
        try {
            // setup port listener
            // add connections to arraylist
            // setup in and out streams
            System.out.println("waiting connetion");
            serverSocket = new ServerSocket(8999);
            // writers = new ArrayList<PrintWriter>();

            while (true) {
                sock = serverSocket.accept();
                sockets.add(sock);
                // PrintWriter writer = new PrintWriter(
                // sock.getOutputStream());
                // writers.add(writer);
                Thread t = new Thread(new ClientHandler(sock));
                t.start();
                System.out.println("connected");
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            System.out.println("fail setup network");

        } finally {
            System.out.println("finally");

        }
    }

    class ClientHandler implements Runnable {
        private BufferedReader in;

        public ClientHandler(Socket sock) {
            // setup a client connection
            try {
                in = new BufferedReader(new InputStreamReader(
                        sock.getInputStream()));
            } catch (IOException e) {
                e.printStackTrace();

                System.out.println("fail classhandler");
            }
        }

        @Override
        public void run() {
            // receive and relay messages back to clients
            String message;
            try {
                while ((message = in.readLine()) != null) {
                    shout(message);
                    System.out.println("client says : "
                            + date.format(cal.getTime()) + message);
                }
            } catch (IOException ex) {
                try {
                    System.out.println("closing");
                    sock.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                sockets.remove(sock);
                System.out.println(sockets);
                ex.printStackTrace();
                System.out.println("fail read message");

            }
        }

        public synchronized void shout(String message) {
            // send message to all clients
            // for (PrintWriter writer : writers) {
            // writer.println(date.format(cal.getTime()) + " " + message
            // + "\n");
            // writer.flush();
            // }
            for (Socket sock : sockets) {
                try {
                    PrintWriter writer = new PrintWriter(sock.getOutputStream());
                    writer.println(date.format(cal.getTime()) + " " + message
                            + "\n");
                    writer.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }

        }

    }

}

=======================================================

    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;

    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;

    public class Client {

        private JTextArea tArea;
        private BufferedReader in;
        private Socket sock;
        private PrintWriter out;

        public static void main(String[] args) {
            new Client().go();
        }

        public void go() {
            JFrame frame = new JFrame("Chat Client");
            final JTextField tField = new JTextField(25);
            tArea = new JTextArea(30, 20);
            JButton button = new JButton("send");
            button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ev) {
                    sendMessage(tField.getText());
                    tField.setText("");
                }
            });
            frame.setSize(300, 500);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(tArea, BorderLayout.NORTH);
            frame.add(tField, BorderLayout.CENTER);
            frame.add(button, BorderLayout.EAST);
            frame.pack();
            setupNetwork();
            Thread t = new Thread(new IncomingReader());
            t.start();
        }

        public void setupNetwork() {
            try {
                sock = new Socket("localhost", 8999);
                in = new BufferedReader(
                        new InputStreamReader(sock.getInputStream()));
                out = new PrintWriter(sock.getOutputStream());
            } catch (IOException ex) {
                ex.printStackTrace();
                System.out.println("fail networking");


}
    }

    class IncomingReader implements Runnable {
        public void run() {
            //receive messages from server
            try {
                String message = null;
                while ((message = in.readLine()) != null) {
                    tArea.append(message + "\n");
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("fail incoming reader");

            }
        }
    }

    public void sendMessage(String message) {
        try {
            out.println(message);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("fail send message");
        }
    }
}

当我关闭一个客户端时,我会收到这个错误提示,我尝试了一些关闭连接的方法,但最终不确定如何摆脱这个错误:
fail read message
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
    at sun.nio.cs.StreamDecoder.read(Unknown Source)
    at java.io.InputStreamReader.read(Unknown Source)
    at java.io.BufferedReader.fill(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at Server$ClassHandler.run(Server.java:63)
    at java.lang.Thread.run(Unknown Source)

我知道这是因为我关闭了一个连接,但它一直抛出这个错误,虽然它不会破坏我的服务器。

这不是解决您问题的方法,但我建议您使用Apache Mina来处理这些事情。因为这个库可以自行处理低级维护,应用程序可以专注于编写逻辑。 - user2880879
4个回答

4
通常的原因是您已经向已由另一端关闭的连接写入了内容。换句话说,这是一个应用程序协议错误。
在这里特定的问题是,当您从服务器中的readLine()获取null时,您应该关闭该套接字并从要通知的writer数组中删除相应的Writer标签。

我一直在尝试,但是我无法想出如何关闭连接或在用户强制退出应用程序时将其删除。 - gallly
@CatznDogz 你找不到close()方法了吗? - user207421
在您的回答中,您说这是因为客户端试图向已关闭的连接写入。但首先是什么让另一方(即服务器端)关闭连接呢? - Salman

2
那是因为当你在客户端使用完 socket 后,应该适当地关闭它。我不是 SWING 大师,但看起来 WindowListener 是你需要的。只需在主窗口关闭时关闭连接即可。
编辑:当你关闭 TCP socket 时,有一点工作需要完成:http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination。当你关闭程序时,这不会发生。操作系统将为您关闭连接并释放所有相关资源,但服务器不会被通知客户端已关闭连接。
编辑 2:演示 服务器:
public class Server {
    public static void main(String args[]) {
          try {
              System.out.println("waiting connetion");
              ServerSocket serverSocket = new ServerSocket(8999);
              while (true) {
                  Socket clientSocket = serverSocket.accept();
                  System.out.println("Connected");
                  Reader reader = new InputStreamReader(
                          clientSocket.getInputStream());
                  reader.read(); // wait for input
                  System.out.println("No exception");
              }
          } catch (IOException ex) {
              System.out.println("Exception");
              ex.printStackTrace();
          }
    }
}

客户:
public class Client {
    public static void main(String args[]) throws Exception {
         Socket sock = new Socket("localhost", 8999);
         System.out.println("Press 1 to close gracefully, any other nuber otherwise");
         Scanner sc = new Scanner(System.in);
         if (sc.nextInt() ==1 ) {
             sock.close();
         } else {
             //do nothing
         }
    }
}

当他关闭客户端连接时会发生这种情况。 - user207421
@EJP 是的,当客户端连接“突然”关闭时会发生这种情况。当客户端关闭连接时,服务器应该得到适当的通知。如果只是由操作系统提供资源,则不会发生这种情况。请参见http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination。 - dimoniy
当一个进程退出时,操作系统会优雅地、非突然地关闭TCP连接。您的非规范参考中没有任何内容表明“如果只是操作系统释放资源,这种情况不会发生”。 - user207421
@EJP 你让我编写代码来证明我的观点。请查看已编辑的答案。 - dimoniy

0

要告诉Java代码所有的HTTP请求都应该通过代理路由,请使用以下片段:

System.setProperty("http.proxyHost", "proxyHost");
System.setProperty("http.proxyPort", "proxyPort");
Authenticator authenticator = new Authenticator() {
     public PasswordAuthentication getPasswordAuthentication() {
    return (new PasswordAuthentication("USERNAME","PASSWORD".toCharArray()));
    }
};
Authenticator.setDefault(authenticator);

System.setProperty设置代理主机和端口。Authenticator应该是您的公司用户名和密码。现在应该可以工作了。


0
socketname.close()方法放在您的客户端中...问题是客户端在服务器读取其流之前就已经完成了...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接