//服务端
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();
}
}
}
}
参考GPT和自己的思路:
Connection reset这个问题通常是由于 socket 结束的方式不一致导致的。在这份代码中,可以看到客户端每次发送消息都是新建一个 Socket 对象,所以每次发送完消息后就关闭了这个 Socket,但是服务端并没有关闭接受消息的 Socket,所以服务端的 Socket 对象一直存在,直到服务端停止监听时才会关闭,这样就导致了客户端关闭了连接,但服务端仍把这个客户端的 Socket 存在了 Vector 中,而且一直发送空消息给客户端,当客户端收到这样的消息就会显示 Connection reset 问题。解决的方法是,客户端和服务端交流时需要明确关闭 Socket 的方式,最好是在双方都收发完消息后关闭 Socket。
不知道你这个问题是否已经解决, 如果还没有解决的话: