服务器之家

服务器之家 > 正文

Java多线程实现聊天客户端和服务器

时间:2020-06-23 13:04     来源/作者:White_Idiot

本文实例为大家分享了java聊天室代码,供大家参考,具体内容如下

主要涉及知识

·Java中GUI程序的编写,包括事件监听机制。
·Java的网络通信编程,ServerSocket,Socket类的使用。
·Java中多线程的编程,Thread类,Runnable接口的使用。

源代码

客户端

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package project1;
 
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
 
import javax.swing.*;
 
public class Client {
 private JFrame clientFrame;
 private JLabel IPLabel;
 private JLabel PortLabel;
 private JLabel sayLabel;
 private JLabel nicknameLabel;
 private JTextField IPText;
 private JTextField PortText;
 private JTextField nicknameText;
 private JTextField sayText;
 private JButton connectButton;
 private JButton nicknameButton;
 private JButton sayButton;
 private JPanel jPanelNorth;
 private JPanel jPanelSouth0;
 private JPanel jPanelSouth1;
 private JPanel jPanelSouth2;
 private JTextArea clientTextArea;
 private JScrollPane scroller;
 private BufferedReader reader;
 private PrintWriter writer;
 private String nickname;
 
 public static void main(String args[]) {
  Client aClient = new Client();
  aClient.startUp();
 }
 
 // 初始化组件
 public Client() {
  nickname = "客户端";
 
  clientFrame = new JFrame();
  jPanelNorth = new JPanel();
  IPLabel = new JLabel("服务器IP", JLabel.LEFT);
  IPText = new JTextField(10);
  PortLabel = new JLabel("服务器端口", JLabel.LEFT);
  PortText = new JTextField(10);
  connectButton = new JButton("连接");
  clientTextArea = new JTextArea();
  scroller = new JScrollPane(clientTextArea);
  jPanelSouth0 = new JPanel();
  jPanelSouth1 = new JPanel();
  jPanelSouth2 = new JPanel();
  nicknameLabel = new JLabel("昵称", JLabel.LEFT);
  nicknameText = new JTextField(nickname, 30);
  nicknameButton = new JButton("确认");
  sayLabel = new JLabel("消息", JLabel.LEFT);
  sayText = new JTextField(30);
  sayButton = new JButton("确认");
 }
 
 // 构建GUI
 private void buildGUI() {
  // 窗口的设置
  clientFrame.setTitle("客户端");
  clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  clientFrame.setSize(550, 550);
 
  // 北区的组件
  jPanelNorth.add(IPLabel);
  jPanelNorth.add(IPText);
  jPanelNorth.add(PortLabel);
  jPanelNorth.add(PortText);
  jPanelNorth.add(connectButton);
  clientFrame.getContentPane().add(BorderLayout.NORTH, jPanelNorth);
 
  // 中间的组件
  clientTextArea.setFocusable(false);
  scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
  scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
  clientFrame.getContentPane().add(BorderLayout.CENTER, scroller);
 
  // 南区的组件
  jPanelSouth1.add(nicknameLabel);
  jPanelSouth1.add(nicknameText);
  jPanelSouth1.add(nicknameButton);
  jPanelSouth2.add(sayLabel);
  jPanelSouth2.add(sayText);
  jPanelSouth2.add(sayButton);
  jPanelSouth0.setLayout(new BoxLayout(jPanelSouth0, BoxLayout.Y_AXIS));
  jPanelSouth0.add(jPanelSouth1);
  jPanelSouth0.add(jPanelSouth2);
  clientFrame.getContentPane().add(BorderLayout.SOUTH, jPanelSouth0);
 
  // 设置窗口可见
  clientFrame.setVisible(true);
 }
 
 // 客户端运行
 public void startUp() {
  buildGUI();
 
  // 接收服务器消息的线程
  Runnable incomingReader = new Runnable() {
   @Override
   public void run() {
    String message;
    try {
     while ((message = reader.readLine()) != null) {
      clientTextArea.append(message + "\n");
     }
    } catch (Exception ex) {
     ex.printStackTrace();
    }
   }
  };
 
  // 监听Connect按钮,实现服务器的连接
  connectButton.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    String aServerIP = IPText.getText();
    String aServerPort = PortText.getText();
 
    if (aServerIP.equals("") || aServerPort.equals("")) {
     JOptionPane.showMessageDialog(clientFrame, "请输入 完整的 IP和端口!");
    } else {
     try {
      @SuppressWarnings("resource")
      Socket clientSocket = new Socket(aServerIP, Integer.parseInt(aServerPort));
      InputStreamReader streamReader = new InputStreamReader(clientSocket.getInputStream());
      reader = new BufferedReader(streamReader);
      writer = new PrintWriter(clientSocket.getOutputStream());
 
      clientTextArea.append("服务器已连接...\n");
 
      Thread readerThread = new Thread(incomingReader);
      readerThread.start();
     } catch (Exception ex) {
      JOptionPane.showMessageDialog(clientFrame, "连接不上服务器!\n请确认 IP 和 端口 输入正确。");
     }
    }
   }
  });
 
  // 监听nickname,设置昵称
  ActionListener nicknameListener = new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    String aText = nicknameText.getText();
    if (!aText.equals("")) {
     nickname = aText;
    }
   }
  };
  nicknameButton.addActionListener(nicknameListener);
  nicknameText.addActionListener(nicknameListener);
  nicknameText.addFocusListener(new FocusListener() {
   @Override
   public void focusGained(FocusEvent e) {
   }
 
   @Override
   public void focusLost(FocusEvent e) {
    String aText = nicknameText.getText();
    if (!aText.equals("")) {
     nickname = aText;
    }
   }
  });
 
  // 发送消息到服务器
  ActionListener SayListener = new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    String aText = sayText.getText();
    if (aText.equals("")) {
     JOptionPane.showMessageDialog(clientFrame, "内容不能为空!");
    } else {
     try {
      writer.println(nickname + ":" + aText);
      writer.flush();
     } catch (Exception ex) {
      ex.printStackTrace();
     }
     sayText.setText("");
    }
   }
  };
  sayButton.addActionListener(SayListener);
  sayText.addActionListener(SayListener);
 
 }
 
}

服务器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package project1;
 
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.*;
 
public class Server {
 private JFrame serverFrame;
 private JLabel portLabel;
 private JLabel sayLabel;
 private JLabel nicknameLabel;
 private JTextField portText;
 private JTextField sayText;
 private JTextField nicknameText;
 private JButton startButton;
 private JButton sayButton;
 private JButton nicknameButton;
 private JPanel jPanelNorth;
 private JPanel jPanelSouth0;
 private JPanel jPanelSouth1;
 private JPanel jPanelSouth2;
 private JScrollPane scroller;
 private JTextArea serverTextArea;
 private ArrayList<PrintWriter> clientOutputStreams;
 private String nickname;
 
 public static void main(String[] args) {
  Server aServer = new Server();
  aServer.startUp();
 }
 
 // 初始化组件
 public Server() {
  nickname = "服务器";
 
  serverFrame = new JFrame();
  jPanelNorth = new JPanel();
  portLabel = new JLabel("端口", JLabel.LEFT);
  portText = new JTextField(30);
  startButton = new JButton("开始");
  serverTextArea = new JTextArea();
  scroller = new JScrollPane(serverTextArea);
  nicknameLabel = new JLabel("昵称", JLabel.LEFT);
  nicknameText = new JTextField(nickname, 30);
  nicknameButton = new JButton("确认");
  jPanelSouth0 = new JPanel();
  jPanelSouth1 = new JPanel();
  jPanelSouth2 = new JPanel();
  sayLabel = new JLabel("消息", JLabel.LEFT);
  sayText = new JTextField(30);
  sayButton = new JButton("确认");
 }
 
 // 构建GUI
 private void buildGUI() {
  // 窗口的设置
  serverFrame.setTitle("服务器");
  serverFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  serverFrame.setSize(550, 550);
 
  // 北区的组件
  jPanelNorth.add(portLabel);
  jPanelNorth.add(portText);
  jPanelNorth.add(startButton);
  serverFrame.getContentPane().add(BorderLayout.NORTH, jPanelNorth);
 
  // 中间的组件
  serverTextArea.setFocusable(false);
  scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
  scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
  serverFrame.getContentPane().add(BorderLayout.CENTER, scroller);
 
  // 南区的组件
  jPanelSouth1.add(nicknameLabel);
  jPanelSouth1.add(nicknameText);
  jPanelSouth1.add(nicknameButton);
  jPanelSouth2.add(sayLabel);
  jPanelSouth2.add(sayText);
  jPanelSouth2.add(sayButton);
  jPanelSouth0.setLayout(new BoxLayout(jPanelSouth0, BoxLayout.Y_AXIS));
  jPanelSouth0.add(jPanelSouth1);
  jPanelSouth0.add(jPanelSouth2);
  serverFrame.getContentPane().add(BorderLayout.SOUTH, jPanelSouth0);
 
  // 设置窗口可见
  serverFrame.setVisible(true);
 }
 
 // 服务器运行
 public void startUp() {
  buildGUI();
 
  // 监听Start按钮,建立端口
  ActionListener startListener = new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    clientOutputStreams = new ArrayList<PrintWriter>();
    String aPort = portText.getText();
 
    if (aPort.equals("")) {
     JOptionPane.showMessageDialog(serverFrame, "请输入正确的端口号!");
    } else {
     try {
      // 等待客户端连接的线程
      Runnable serverRunnable = new Runnable() {
       @Override
       public void run() {
        ServerSocket serverSocket;
        try {
         serverSocket = new ServerSocket(Integer.parseInt(aPort));
         serverTextArea.append("正在等待客户端连接...\n");
         while (true) {
          Socket clientSocket = serverSocket.accept();
          serverTextArea.append("客户端已连接...\n");
 
          PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
          clientOutputStreams.add(writer);
 
          Thread t = new Thread(new ClientHandler(clientSocket));
          t.start();
         }
        } catch (NumberFormatException | IOException e) {
         e.printStackTrace();
        }
       }
      };
      Thread serverThread = new Thread(serverRunnable);
      serverThread.start();
     } catch (Exception ex) {
      ex.printStackTrace();
     }
    }
   }
  };
  startButton.addActionListener(startListener);
  portText.addActionListener(startListener);
 
  // 监听nickname,设置昵称
  ActionListener nicknameListener = new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    String aText = nicknameText.getText();
    if (!aText.equals("")) {
     nickname = aText;
    }
   }
  };
  nicknameButton.addActionListener(nicknameListener);
  nicknameText.addActionListener(nicknameListener);
  nicknameText.addFocusListener(new FocusListener() {
   @Override
   public void focusGained(FocusEvent e) {
   }
 
   @Override
   public void focusLost(FocusEvent e) {
    String aText = nicknameText.getText();
    if (!aText.equals("")) {
     nickname = aText;
    }
   }
  });
 
  // 监听Say按钮,发送消息
  ActionListener SayListener = new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
    String aText = sayText.getText();
    if (!aText.equals("")) {
     aText = nickname + ":" + aText;
     sendToEveryClient(aText);
     serverTextArea.append(aText + "\n");
     sayText.setText("");
    } else {
     JOptionPane.showMessageDialog(serverFrame, "内容不能为空!");
    }
   }
  };
  sayButton.addActionListener(SayListener);
  sayText.addActionListener(SayListener);
 }
 
 // 多客户端的线程
 public class ClientHandler implements Runnable {
  BufferedReader bReader;
  Socket aSocket;
 
  public ClientHandler(Socket clientSocket) {
   try {
    aSocket = clientSocket;
    InputStreamReader isReader = new InputStreamReader(aSocket.getInputStream());
    bReader = new BufferedReader(isReader);
   } catch (Exception ex) {
    ex.printStackTrace();
   }
  }
 
  @Override
  public void run() {
   String message;
   try {
    while ((message = bReader.readLine()) != null) {
     sendToEveryClient(message);
     serverTextArea.append(message + "\n");
    }
   } catch (Exception ex) {
    ex.printStackTrace();
   }
  }
 }
 
 // 发送消息给所有客户端的方法
 private void sendToEveryClient(String message) {
  Iterator<PrintWriter> it = clientOutputStreams.iterator();
  while (it.hasNext()) {
   try {
    PrintWriter writer = (PrintWriter) it.next();
    writer.println(message);
    writer.flush();
   } catch (Exception ex) {
    ex.printStackTrace();
   }
  }
 }
 
}

GUI运行截图:

Java多线程实现聊天客户端和服务器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享 2020-04-07
沙雕群名称大全2019精选 今年最火的微信群名沙雕有创意
沙雕群名称大全2019精选 今年最火的微信群名沙雕有创意 2019-07-07
玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分
玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分 2019-06-21
男生常说24816是什么意思?女生说13579是什么意思?
男生常说24816是什么意思?女生说13579是什么意思? 2019-09-17
返回顶部