TCP网络传输出现Connection reset问题

//服务端
public class ServerTalk extends JFrame {
    public static void main(String[] args) {
        new ServerTalk();
    }
    private Vector vector = new Vector<>();
    private Socket s;
    private ServerSocket ss = null;
    private final Font font = new Font("宋体", Font.BOLD, 20);
    private Container c;
    private JLabel label;
    private JTextField txt;  // 端口号
    private JButton b1,b2;   //    开始监听 停止监听
    public ServerTalk() {
        c = getContentPane();
        setLayout(null);
        setSize(320, 220);
        setTitle("监听服务");
        init();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(this.EXIT_ON_CLOSE);
        setVisible(true);
    }
    private void init() {
        label = new JLabel("端口号:");
        label.setFont(font);
        label.setBounds(40, 10, 100, 50);
        label.setHorizontalAlignment(0);
        c.add(label);
        txt = new JTextField();
        txt.setFont(font);
        txt.setBounds(140, 10, 80, 50);
        txt.setHorizontalAlignment(JTextField.CENTER);
        c.add(txt);
        b1 = new JButton("开始监听");
        b1.setBounds(20, 85, 120, 50);
        b1.setFont(font);
        c.add(b1);
        startListen();
        b2 = new JButton("停止监听");
        b2.setBounds(165, 85, 120, 50);
        b2.setFont(font);
        c.add(b2);
        endListen();
    }
    private void startListen() {
        b1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String port = txt.getText();
                if(port.equals("")) {
                    return;
                }
                try {
                    ss = new ServerSocket(Integer.valueOf(port));
                } catch (NumberFormatException | IOException e1) {
                    e1.printStackTrace();
                }
                new Thread() {
                    @Override
                    public void run() {
                        while (true) {
                            try {
                                s = ss.accept();
                                vector.add(s);
                                new Thread(new ReadAllClient(s)).start();
                            } catch (IOException e) {} 
                              catch (Exception e2) {}
                        }
                    }
                }.start();
                b1.setEnabled(false);
            }
        });
    }
    class ReadAllClient implements Runnable {
        private Socket s;
        public ReadAllClient(Socket s) {
            this.s = s;
        }
        @Override
        public void run() {
            try {
                String msg = "";
                BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
                while(!(msg = in.readLine()).equals("bye")) {
                    fenfa(msg);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        private void fenfa(String msg) {
            for(Socket socket : vector) {
                PrintWriter out;
                try {
                    out = new PrintWriter(s.getOutputStream(),true);
                    out.println(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
    }
    private void endListen() {
        b2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                b1.setEnabled(true);
                txt.setText("");
                if(!ss.isClosed()) {
                    try {
                        ss.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    ss = null;
                }
            }
        });
    }
}


//客户端
public class ClientTalk extends JFrame{
    public static void main(String[] args) {
        new ClientTalk();
    }
    private Socket s;
    private final Font font = new Font("宋体", Font.BOLD, 20);
    private Container c;
    private JLabel label1,label2,label3;
    private JTextField txt1,txt2,txt3;   //    昵称&&主机号&&端口号
    private JButton b;   //    开始连接
    public ClientTalk() {
        c = getContentPane();
        setLayout(null);
        setSize(300, 330);
        setTitle("连接服务");
        init();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(this.EXIT_ON_CLOSE);
        setVisible(true);
    }
    private void init() {
        label1 = new JLabel("昵称:");
        label2 = new JLabel("主机号:");
        label3 = new JLabel("端口号:");
        label1.setBounds(15,10,100,50);
        label2.setBounds(15,70,100,50);
        label3.setBounds(15,130,100,50);
        label1.setFont(font);
        label2.setFont(font);
        label3.setFont(font);
        c.add(label1);
        c.add(label2);
        c.add(label3);
        label1.setHorizontalAlignment(JLabel.RIGHT);
        label2.setHorizontalAlignment(JLabel.RIGHT);
        label3.setHorizontalAlignment(JLabel.RIGHT);
        txt1 = new JTextField();
        txt2 = new JTextField();
        txt3 = new JTextField();
        txt1.setBounds(115,10,120,50);
        txt2.setBounds(115,70,120,50);
        txt3.setBounds(115,130,120,50);
        txt1.setFont(font);
        txt2.setFont(new Font("宋体", Font.BOLD, 15));
        txt3.setFont(font);
        txt1.setHorizontalAlignment(JTextField.CENTER);
        txt2.setHorizontalAlignment(JTextField.CENTER);
        txt3.setHorizontalAlignment(JTextField.CENTER);
        c.add(txt1);
        c.add(txt2);
        c.add(txt3);
        b = new JButton("开始连接");
        b.setBounds(70, 200, 150, 50);
        b.setFont(font);
        c.add(b);
        startConnect();
    }
    private void startConnect() {
        b.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String name = txt1.getText();
                String host = txt2.getText();
                String port = txt3.getText();
                if(name.equals("") || host.equals("") || port.equals("")) {
                    return;
                }
                try {
                    s = new Socket(host, Integer.parseInt(port));
                } catch (NumberFormatException | IOException e1) {
                    e1.printStackTrace();
                }
                new Talk(name,s);
                ClientTalk.this.dispose();
            }
        });
    }
}



//主界面
public class Talk extends JFrame{
    private String name;
    private Socket s;
    private final Font font = new Font("宋体", Font.BOLD, 15);
    private Container c;
    private JTextArea area1,area2;
    private JScrollPane sp1,sp2;
    private JButton b;   //    发送
    private JLabel label;//    昵称
    public Talk(String name,Socket s) {
        this.name = name;
        this.s = s;
        c = getContentPane();
        setLayout(null);
        setSize(600, 600);
        init();
        send("【"+name+"】进入了房间");
        new Thread(new ReadMsg(s)).start();
        label.setText("昵称:"+name);
        setTitle("聊天室");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(this.EXIT_ON_CLOSE);
        setVisible(true);
    }
    private void init() {
        area1 = new JTextArea();
        area1.setFont(font);
        sp1 = new JScrollPane(area1);
        sp1.setBounds(20, 400, 460, 155);
        c.add(sp1);
        label = new JLabel("无名氏");
        label.setBounds(480,400,110,50);
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setFont(font);
        c.add(label);
        b = new JButton("发送");
        b.setBounds(490, 480, 85, 50);
        b.setHorizontalAlignment(JLabel.CENTER);
        b.setFont(font);
        c.add(b);
        emitte();
        area2 = new JTextArea();
        area2.setEditable(false);
        sp2 = new JScrollPane(area2);
        sp2.setBounds(20,10,545,380);
        c.add(sp2);
    }
    private void emitte() {
        b.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String msg = area1.getText();
                if(msg.equals("")) {
                    return;
                }
                send(msg);
                area1.setText("");
            }
        });
    }
    protected void send(String msg) {
        try {
            PrintWriter out = new PrintWriter(s.getOutputStream());
            out.println(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    class ReadMsg implements Runnable{
        private Socket s;
        public ReadMsg(Socket s) {
            this.s = s;
        }
        @Override
        public void run() {
            try {
                BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
                String msg = "";
                while(!(msg = in.readLine()).equals("bye")) {
                    area2.append(msg+"\n");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }    
        }
    }
}


img


TCP网络传输通过客户端发消息,服务端监听到所有客户端,一有消息就分发给所有客户端,客户端读服务端发来的消息,显示在主界面上,客户端把socket传给Talk类,在Talk类收发消息,中间所有的socket都没有关,为什么出现了Connection reset问题。

参考GPT和自己的思路:

Connection reset这个问题通常是由于 socket 结束的方式不一致导致的。在这份代码中,可以看到客户端每次发送消息都是新建一个 Socket 对象,所以每次发送完消息后就关闭了这个 Socket,但是服务端并没有关闭接受消息的 Socket,所以服务端的 Socket 对象一直存在,直到服务端停止监听时才会关闭,这样就导致了客户端关闭了连接,但服务端仍把这个客户端的 Socket 存在了 Vector 中,而且一直发送空消息给客户端,当客户端收到这样的消息就会显示 Connection reset 问题。解决的方法是,客户端和服务端交流时需要明确关闭 Socket 的方式,最好是在双方都收发完消息后关闭 Socket。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^