- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章基于java编写局域网多人聊天室由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
由于需要制作网络计算机网络课程设计,并且不想搞网络布线或者局域网路由器配置等等这种完全搞不懂的东西,最后决定使用socket基于java编写一个局域网聊天室:
关于socket以及网络编程的相关知识详见我另一篇文章:Java基于socket编程 。
程序基于C/S结构,即客户端服务器模式。 服务器: 默认ip为本机ip 需要双方确定一个端口号 可设置最大连接人数 可启动与关闭 界面显示在线用户人以及姓名(本机不在此显示) 客户端: 需要手动设置服务器ip地址(局域网) 手动设置端口号 输入姓名 可连接可断开 程序运行界面如下:
服务器:
客户端:
具体代码我会在最后上传。 软件有很多不足,其中比如: 没有与数据库有任何交集 优化:可将所有用户存放在数据库中,以及将聊天记录也放入数据库中 没有实现一对一聊天 优化:需重新定义一对一聊天的方法 还有许多不足的地方,日后有兴趣再回来慢慢研究 。
下面为该程序三个代码: User.java 。
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
|
public
class
User{
/**
* 用户信息类
* 用于记录用户个人信息:姓名以及IP
*/
private
String name;
private
String ip;
public
User(String name, String ip) {
this
.name = name;
this
.ip = ip;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getIp() {
return
ip;
}
public
void
setIp(String ip) {
this
.ip = ip;
}
}
|
Server_more.java 。
。
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
|
import
java.awt.BorderLayout;
import
java.awt.Color;
import
java.awt.GridLayout;
import
java.awt.Toolkit;
import
java.awt.event.ActionEvent;
import
java.awt.event.ActionListener;
import
java.awt.event.WindowAdapter;
import
java.awt.event.WindowEvent;
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.io.PrintWriter;
import
java.net.BindException;
import
java.net.ServerSocket;
import
java.net.Socket;
import
java.util.ArrayList;
import
java.util.StringTokenizer;
import
javax.swing.DefaultListModel;
import
javax.swing.JButton;
import
javax.swing.JFrame;
import
javax.swing.JLabel;
import
javax.swing.JList;
import
javax.swing.JOptionPane;
import
javax.swing.JPanel;
import
javax.swing.JScrollPane;
import
javax.swing.JSplitPane;
import
javax.swing.JTextArea;
import
javax.swing.JTextField;
import
javax.swing.border.TitledBorder;
public
class
Server_more {
private
JFrame frame;
private
JTextArea contentArea;
//文本域
private
JTextField txt_message;
//用于显示文本信息
private
JTextField txt_max;
//设置最大连接人数
private
JTextField txt_port;
//设置端口号
private
JButton btn_start;
//开始按钮
private
JButton btn_stop;
//断开按钮
private
JButton btn_send;
//发送按钮
private
JPanel northPanel;
//北方面板
private
JPanel southPanel;
//南方面板
private
JScrollPane rightPanel;
//左边滚动条
private
JScrollPane leftPanel;
//右边滚动条
private
JSplitPane centerSplit;
//分割线
private
JList userList;
//列表组件
private
DefaultListModel listModel;
private
ServerSocket serverSocket;
private
ServerThread serverThread;
private
ArrayList<ClientThread> clients;
private
boolean
isStart =
false
;
// 主方法,程序执行入口
public
static
void
main(String[] args) {
new
Server_more();
}
// 执行消息发送
public
void
send() {
if
(!isStart) {
JOptionPane.showMessageDialog(frame,
"服务器还未启动,不能发送消息!"
,
"错误"
,
JOptionPane.ERROR_MESSAGE);
return
;
}
if
(clients.size() ==
0
) {
JOptionPane.showMessageDialog(frame,
"没有用户在线,不能发送消息!"
,
"错误"
,
JOptionPane.ERROR_MESSAGE);
return
;
}
String message = txt_message.getText().trim();
if
(message ==
null
|| message.equals(
""
)) {
JOptionPane.showMessageDialog(frame,
"消息不能为空!"
,
"错误"
,
JOptionPane.ERROR_MESSAGE);
return
;
}
sendServerMessage(message);
// 群发服务器消息
contentArea.append(
"服务器:"
+ txt_message.getText() +
"\r\n"
);
txt_message.setText(
null
);
}
// 构造放法
public
Server_more() {
frame =
new
JFrame(
"服务器"
);
// 更改JFrame的图标:
//frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.getResource("qq.png")));
//frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Server.class.getResource("qq.png")));
contentArea =
new
JTextArea();
contentArea.setEditable(
false
);
contentArea.setForeground(Color.blue);
txt_message =
new
JTextField();
txt_max =
new
JTextField(
"30"
);
txt_port =
new
JTextField(
"6666"
);
btn_start =
new
JButton(
"启动"
);
btn_stop =
new
JButton(
"停止"
);
btn_send =
new
JButton(
"发送"
);
btn_stop.setEnabled(
false
);
listModel =
new
DefaultListModel();
userList =
new
JList(listModel);
southPanel =
new
JPanel(
new
BorderLayout());
southPanel.setBorder(
new
TitledBorder(
"写消息"
));
southPanel.add(txt_message,
"Center"
);
southPanel.add(btn_send,
"East"
);
leftPanel =
new
JScrollPane(userList);
leftPanel.setBorder(
new
TitledBorder(
"在线用户"
));
rightPanel =
new
JScrollPane(contentArea);
rightPanel.setBorder(
new
TitledBorder(
"消息显示区"
));
centerSplit =
new
JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel,
rightPanel);
centerSplit.setDividerLocation(
100
);
northPanel =
new
JPanel();
northPanel.setLayout(
new
GridLayout(
1
,
6
));
northPanel.add(
new
JLabel(
"人数上限"
));
northPanel.add(txt_max);
northPanel.add(
new
JLabel(
"端口"
));
northPanel.add(txt_port);
northPanel.add(btn_start);
northPanel.add(btn_stop);
northPanel.setBorder(
new
TitledBorder(
"配置信息"
));
frame.setLayout(
new
BorderLayout());
frame.add(northPanel,
"North"
);
frame.add(centerSplit,
"Center"
);
frame.add(southPanel,
"South"
);
frame.setSize(
600
,
400
);
//frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());//设置全屏
int
screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
int
screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
frame.setLocation((screen_width - frame.getWidth()) /
2
,
(screen_height - frame.getHeight()) /
2
);
frame.setVisible(
true
);
// 关闭窗口时事件
frame.addWindowListener(
new
WindowAdapter() {
public
void
windowClosing(WindowEvent e) {
if
(isStart) {
closeServer();
// 关闭服务器
}
System.exit(
0
);
// 退出程序
}
});
// 文本框按回车键时事件
txt_message.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
send();
}
});
// 单击发送按钮时事件
btn_send.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent arg0) {
send();
}
});
// 单击启动服务器按钮时事件
btn_start.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
if
(isStart) {
JOptionPane.showMessageDialog(frame,
"服务器已处于启动状态,不要重复启动!"
,
"错误"
, JOptionPane.ERROR_MESSAGE);
return
;
}
int
max;
int
port;
try
{
try
{
max = Integer.parseInt(txt_max.getText());
}
catch
(Exception e1) {
throw
new
Exception(
"人数上限为正整数!"
);
}
if
(max <=
0
) {
throw
new
Exception(
"人数上限为正整数!"
);
}
try
{
port = Integer.parseInt(txt_port.getText());
}
catch
(Exception e1) {
throw
new
Exception(
"端口号为正整数!"
);
}
if
(port <=
0
) {
throw
new
Exception(
"端口号 为正整数!"
);
}
serverStart(max, port);
contentArea.append(
"服务器已成功启动!人数上限:"
+ max +
",端口:"
+ port
+
"\r\n"
);
JOptionPane.showMessageDialog(frame,
"服务器成功启动!"
);
btn_start.setEnabled(
false
);
txt_max.setEnabled(
false
);
txt_port.setEnabled(
false
);
btn_stop.setEnabled(
true
);
}
catch
(Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"错误"
, JOptionPane.ERROR_MESSAGE);
}
}
});
// 单击停止服务器按钮时事件
btn_stop.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
if
(!isStart) {
JOptionPane.showMessageDialog(frame,
"服务器还未启动,无需停止!"
,
"错误"
,
JOptionPane.ERROR_MESSAGE);
return
;
}
try
{
closeServer();
btn_start.setEnabled(
true
);
txt_max.setEnabled(
true
);
txt_port.setEnabled(
true
);
btn_stop.setEnabled(
false
);
contentArea.append(
"服务器成功停止!\r\n"
);
JOptionPane.showMessageDialog(frame,
"服务器成功停止!"
);
}
catch
(Exception exc) {
JOptionPane.showMessageDialog(frame,
"停止服务器发生异常!"
,
"错误"
,
JOptionPane.ERROR_MESSAGE);
}
}
});
}
// 启动服务器
public
void
serverStart(
int
max,
int
port)
throws
java.net.BindException {
try
{
clients =
new
ArrayList<ClientThread>();
serverSocket =
new
ServerSocket(port);
serverThread =
new
ServerThread(serverSocket, max);
serverThread.start();
isStart =
true
;
}
catch
(BindException e) {
isStart =
false
;
throw
new
BindException(
"端口号已被占用,请换一个!"
);
}
catch
(Exception e1) {
e1.printStackTrace();
isStart =
false
;
throw
new
BindException(
"启动服务器异常!"
);
}
}
// 关闭服务器
@SuppressWarnings
(
"deprecation"
)
public
void
closeServer() {
try
{
if
(serverThread !=
null
)
serverThread.stop();
// 停止服务器线程
for
(
int
i = clients.size() -
1
; i >=
0
; i--) {
// 给所有在线用户发送关闭命令
clients.get(i).getWriter().println(
"CLOSE"
);
clients.get(i).getWriter().flush();
// 释放资源
clients.get(i).stop();
// 停止此条为客户端服务的线程
clients.get(i).reader.close();
clients.get(i).writer.close();
clients.get(i).socket.close();
clients.remove(i);
}
if
(serverSocket !=
null
) {
serverSocket.close();
// 关闭服务器端连接
}
listModel.removeAllElements();
// 清空用户列表
isStart =
false
;
}
catch
(IOException e) {
e.printStackTrace();
isStart =
true
;
}
}
// 群发服务器消息
public
void
sendServerMessage(String message) {
for
(
int
i = clients.size() -
1
; i >=
0
; i--) {
clients.get(i).getWriter().println(
"服务器:"
+ message +
"(多人发送)"
);
clients.get(i).getWriter().flush();
}
}
// 服务器线程
class
ServerThread
extends
Thread {
private
ServerSocket serverSocket;
private
int
max;
// 人数上限
// 服务器线程的构造方法
public
ServerThread(ServerSocket serverSocket,
int
max) {
this
.serverSocket = serverSocket;
this
.max = max;
}
public
void
run() {
while
(
true
) {
// 不停的等待客户端的链接
try
{
Socket socket = serverSocket.accept();
if
(clients.size() == max) {
// 如果已达人数上限
BufferedReader r =
new
BufferedReader(
new
InputStreamReader(socket.getInputStream()));
PrintWriter w =
new
PrintWriter(socket
.getOutputStream());
// 接收客户端的基本用户信息
String inf = r.readLine();
StringTokenizer st =
new
StringTokenizer(inf,
"@"
);
User user =
new
User(st.nextToken(), st.nextToken());
// 反馈连接成功信息
w.println(
"MAX@服务器:对不起,"
+ user.getName()
+ user.getIp() +
",服务器在线人数已达上限,请稍后尝试连接!"
);
w.flush();
// 释放资源
r.close();
w.close();
socket.close();
continue
;
}
ClientThread client =
new
ClientThread(socket);
client.start();
// 开启对此客户端服务的线程
clients.add(client);
listModel.addElement(client.getUser().getName());
// 更新在线列表
contentArea.append(client.getUser().getName()
+ client.getUser().getIp() +
"上线!\r\n"
);
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
}
// 为一个客户端服务的线程
class
ClientThread
extends
Thread {
private
Socket socket;
private
BufferedReader reader;
private
PrintWriter writer;
private
User user;
public
BufferedReader getReader() {
return
reader;
}
public
PrintWriter getWriter() {
return
writer;
}
public
User getUser() {
return
user;
}
// 客户端线程的构造方法
public
ClientThread(Socket socket) {
try
{
this
.socket = socket;
reader =
new
BufferedReader(
new
InputStreamReader(socket
.getInputStream()));
writer =
new
PrintWriter(socket.getOutputStream());
// 接收客户端的基本用户信息
String inf = reader.readLine();
StringTokenizer st =
new
StringTokenizer(inf,
"@"
);
user =
new
User(st.nextToken(), st.nextToken());
// 反馈连接成功信息
writer.println(user.getName() + user.getIp() +
"与服务器连接成功!"
);
writer.flush();
// 反馈当前在线用户信息
if
(clients.size() >
0
) {
String temp =
""
;
for
(
int
i = clients.size() -
1
; i >=
0
; i--) {
temp += (clients.get(i).getUser().getName() +
"/"
+ clients
.get(i).getUser().getIp())
+
"@"
;
}
writer.println(
"USERLIST@"
+ clients.size() +
"@"
+ temp);
writer.flush();
}
// 向所有在线用户发送该用户上线命令
for
(
int
i = clients.size() -
1
; i >=
0
; i--) {
clients.get(i).getWriter().println(
"ADD@"
+ user.getName() + user.getIp());
clients.get(i).getWriter().flush();
}
}
catch
(IOException e) {
e.printStackTrace();
}
}
@SuppressWarnings
(
"deprecation"
)
public
void
run() {
// 不断接收客户端的消息,进行处理。
String message =
null
;
while
(
true
) {
try
{
message = reader.readLine();
// 接收客户端消息
if
(message.equals(
"CLOSE"
))
// 下线命令
{
contentArea.append(
this
.getUser().getName()
+
this
.getUser().getIp() +
"下线!\r\n"
);
// 断开连接释放资源
reader.close();
writer.close();
socket.close();
// 向所有在线用户发送该用户的下线命令
for
(
int
i = clients.size() -
1
; i >=
0
; i--) {
clients.get(i).getWriter().println(
"DELETE@"
+ user.getName());
clients.get(i).getWriter().flush();
}
listModel.removeElement(user.getName());
// 更新在线列表
// 删除此条客户端服务线程
for
(
int
i = clients.size() -
1
; i >=
0
; i--) {
if
(clients.get(i).getUser() == user) {
ClientThread temp = clients.get(i);
clients.remove(i);
// 删除此用户的服务线程
temp.stop();
// 停止这条服务线程
return
;
}
}
}
else
{
dispatcherMessage(message);
// 转发消息
}
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
// 转发消息
public
void
dispatcherMessage(String message) {
StringTokenizer stringTokenizer =
new
StringTokenizer(message,
"@"
);
String source = stringTokenizer.nextToken();
String owner = stringTokenizer.nextToken();
String content = stringTokenizer.nextToken();
message = source +
":"
+ content;
contentArea.append(message +
"\r\n"
);
if
(owner.equals(
"ALL"
)) {
// 群发
for
(
int
i = clients.size() -
1
; i >=
0
; i--) {
clients.get(i).getWriter().println(message +
"(多人发送)"
);
clients.get(i).getWriter().flush();
}
}
}
}
}
|
Client_more.java 。
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
|
import
java.awt.BorderLayout;
import
java.awt.Color;
import
java.awt.GridLayout;
import
java.awt.Toolkit;
import
java.awt.event.ActionEvent;
import
java.awt.event.ActionListener;
import
java.awt.event.WindowAdapter;
import
java.awt.event.WindowEvent;
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.io.PrintWriter;
import
java.net.Socket;
import
java.util.HashMap;
import
java.util.Map;
import
java.util.StringTokenizer;
import
javax.swing.DefaultListModel;
import
javax.swing.JButton;
import
javax.swing.JFrame;
import
javax.swing.JLabel;
import
javax.swing.JList;
import
javax.swing.JOptionPane;
import
javax.swing.JPanel;
import
javax.swing.JScrollPane;
import
javax.swing.JSplitPane;
import
javax.swing.JTextArea;
import
javax.swing.JTextField;
import
javax.swing.border.TitledBorder;
public
class
Client_more{
private
JFrame frame;
private
JList userList;
private
JTextArea textArea;
private
JTextField textField;
private
JTextField txt_port;
private
JTextField txt_hostIp;
private
JTextField txt_name;
private
JButton btn_start;
private
JButton btn_stop;
private
JButton btn_send;
private
JPanel northPanel;
private
JPanel southPanel;
private
JScrollPane rightScroll;
private
JScrollPane leftScroll;
private
JSplitPane centerSplit;
private
DefaultListModel listModel;
private
boolean
isConnected =
false
;
private
Socket socket;
private
PrintWriter writer;
private
BufferedReader reader;
private
MessageThread messageThread;
// 负责接收消息的线程
private
Map<String, User> onLineUsers =
new
HashMap<String, User>();
// 所有在线用户
// 主方法,程序入口
public
static
void
main(String[] args) {
new
Client_more();
}
// 执行发送
public
void
send() {
if
(!isConnected) {
JOptionPane.showMessageDialog(frame,
"还没有连接服务器,无法发送消息!"
,
"错误"
,
JOptionPane.ERROR_MESSAGE);
return
;
}
String message = textField.getText().trim();
if
(message ==
null
|| message.equals(
""
)) {
JOptionPane.showMessageDialog(frame,
"消息不能为空!"
,
"错误"
,
JOptionPane.ERROR_MESSAGE);
return
;
}
sendMessage(frame.getTitle() +
"@"
+
"ALL"
+
"@"
+ message);
textField.setText(
null
);
}
// 构造方法
public
Client_more() {
textArea =
new
JTextArea();
textArea.setEditable(
false
);
textArea.setForeground(Color.blue);
textField =
new
JTextField();
txt_port =
new
JTextField(
"6666"
);
txt_hostIp =
new
JTextField(
"127.0.0.1"
);
txt_name =
new
JTextField(
"吴承潜"
);
btn_start =
new
JButton(
"连接"
);
btn_stop =
new
JButton(
"断开"
);
btn_send =
new
JButton(
"发送"
);
listModel =
new
DefaultListModel();
userList =
new
JList(listModel);
northPanel =
new
JPanel();
northPanel.setLayout(
new
GridLayout(
1
,
7
));
northPanel.add(
new
JLabel(
"端口"
));
northPanel.add(txt_port);
northPanel.add(
new
JLabel(
"服务器IP"
));
northPanel.add(txt_hostIp);
northPanel.add(
new
JLabel(
"姓名"
));
northPanel.add(txt_name);
northPanel.add(btn_start);
northPanel.add(btn_stop);
northPanel.setBorder(
new
TitledBorder(
"连接信息"
));
rightScroll =
new
JScrollPane(textArea);
rightScroll.setBorder(
new
TitledBorder(
"消息显示区"
));
leftScroll =
new
JScrollPane(userList);
leftScroll.setBorder(
new
TitledBorder(
"在线用户"
));
southPanel =
new
JPanel(
new
BorderLayout());
southPanel.add(textField,
"Center"
);
southPanel.add(btn_send,
"East"
);
southPanel.setBorder(
new
TitledBorder(
"写消息"
));
centerSplit =
new
JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScroll,
rightScroll);
centerSplit.setDividerLocation(
100
);
frame =
new
JFrame(
"客户机"
);
// 更改JFrame的图标:
// frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.getResource("qq.png")));
frame.setLayout(
new
BorderLayout());
frame.add(northPanel,
"North"
);
frame.add(centerSplit,
"Center"
);
frame.add(southPanel,
"South"
);
frame.setSize(
600
,
400
);
int
screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
int
screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
frame.setLocation((screen_width - frame.getWidth()) /
2
,
(screen_height - frame.getHeight()) /
2
);
frame.setVisible(
true
);
// 写消息的文本框中按回车键时事件
textField.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent arg0) {
send();
}
});
// 单击发送按钮时事件
btn_send.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
send();
}
});
// 单击连接按钮时事件
btn_start.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
int
port;
if
(isConnected) {
JOptionPane.showMessageDialog(frame,
"已处于连接上状态,不要重复连接!"
,
"错误"
, JOptionPane.ERROR_MESSAGE);
return
;
}
try
{
try
{
port = Integer.parseInt(txt_port.getText().trim());
}
catch
(NumberFormatException e2) {
throw
new
Exception(
"端口号不符合要求!端口为整数!"
);
}
String hostIp = txt_hostIp.getText().trim();
String name = txt_name.getText().trim();
if
(name.equals(
""
) || hostIp.equals(
""
)) {
throw
new
Exception(
"姓名、服务器IP不能为空!"
);
}
boolean
flag = connectServer(port, hostIp, name);
if
(flag ==
false
) {
throw
new
Exception(
"与服务器连接失败!"
);
}
frame.setTitle(name);
JOptionPane.showMessageDialog(frame,
"成功连接!"
);
}
catch
(Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"错误"
, JOptionPane.ERROR_MESSAGE);
}
}
});
// 单击断开按钮时事件
btn_stop.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
if
(!isConnected) {
JOptionPane.showMessageDialog(frame,
"已处于断开状态,不要重复断开!"
,
"错误"
, JOptionPane.ERROR_MESSAGE);
return
;
}
try
{
boolean
flag = closeConnection();
// 断开连接
if
(flag ==
false
) {
throw
new
Exception(
"断开连接发生异常!"
);
}
JOptionPane.showMessageDialog(frame,
"成功断开!"
);
}
catch
(Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"错误"
, JOptionPane.ERROR_MESSAGE);
}
}
});
// 关闭窗口时事件
frame.addWindowListener(
new
WindowAdapter() {
public
void
windowClosing(WindowEvent e) {
if
(isConnected) {
closeConnection();
// 关闭连接
}
System.exit(
0
);
// 退出程序
}
});
}
/**
* 连接服务器
*
* @param port
* @param hostIp
* @param name
*/
public
boolean
connectServer(
int
port, String hostIp, String name) {
// 连接服务器
try
{
socket =
new
Socket(hostIp, port);
// 根据端口号和服务器ip建立连接
writer =
new
PrintWriter(socket.getOutputStream());
reader =
new
BufferedReader(
new
InputStreamReader(socket
.getInputStream()));
// 发送客户端用户基本信息(用户名和ip地址)
sendMessage(name +
"@"
+ socket.getLocalAddress().toString());
// 开启接收消息的线程
messageThread =
new
MessageThread(reader, textArea);
messageThread.start();
isConnected =
true
;
// 已经连接上了
return
true
;
}
catch
(Exception e) {
textArea.append(
"与端口号为:"
+ port +
" IP地址为:"
+ hostIp
+
" 的服务器连接失败!"
+
"\r\n"
);
isConnected =
false
;
// 未连接上
return
false
;
}
}
/**
* 发送消息
*
* @param message
*/
public
void
sendMessage(String message) {
writer.println(message);
writer.flush();
}
/**
* 客户端主动关闭连接
*/
@SuppressWarnings
(
"deprecation"
)
public
synchronized
boolean
closeConnection() {
try
{
sendMessage(
"CLOSE"
);
// 发送断开连接命令给服务器
messageThread.stop();
// 停止接受消息线程
// 释放资源
if
(reader !=
null
) {
reader.close();
}
if
(writer !=
null
) {
writer.close();
}
if
(socket !=
null
) {
socket.close();
}
isConnected =
false
;
return
true
;
}
catch
(IOException e1) {
e1.printStackTrace();
isConnected =
true
;
return
false
;
}
}
// 不断接收消息的线程
class
MessageThread
extends
Thread {
private
BufferedReader reader;
private
JTextArea textArea;
// 接收消息线程的构造方法
public
MessageThread(BufferedReader reader, JTextArea textArea) {
this
.reader = reader;
this
.textArea = textArea;
}
// 被动的关闭连接
public
synchronized
void
closeCon()
throws
Exception {
// 清空用户列表
listModel.removeAllElements();
// 被动的关闭连接释放资源
if
(reader !=
null
) {
reader.close();
}
if
(writer !=
null
) {
writer.close();
}
if
(socket !=
null
) {
socket.close();
}
isConnected =
false
;
// 修改状态为断开
}
public
void
run() {
String message =
""
;
while
(
true
) {
try
{
message = reader.readLine();
StringTokenizer stringTokenizer =
new
StringTokenizer(
message,
"/@"
);
String command = stringTokenizer.nextToken();
// 命令
if
(command.equals(
"CLOSE"
))
// 服务器已关闭命令
{
textArea.append(
"服务器已关闭!\r\n"
);
closeCon();
// 被动的关闭连接
return
;
// 结束线程
}
else
if
(command.equals(
"ADD"
)) {
// 有用户上线更新在线列表
String username =
""
;
String userIp =
""
;
if
((username = stringTokenizer.nextToken()) !=
null
&& (userIp = stringTokenizer.nextToken()) !=
null
) {
User user =
new
User(username, userIp);
onLineUsers.put(username, user);
listModel.addElement(username);
}
}
else
if
(command.equals(
"DELETE"
)) {
// 有用户下线更新在线列表
String username = stringTokenizer.nextToken();
User user = (User) onLineUsers.get(username);
onLineUsers.remove(user);
listModel.removeElement(username);
}
else
if
(command.equals(
"USERLIST"
)) {
// 加载在线用户列表
int
size = Integer
.parseInt(stringTokenizer.nextToken());
String username =
null
;
String userIp =
null
;
for
(
int
i =
0
; i < size; i++) {
username = stringTokenizer.nextToken();
userIp = stringTokenizer.nextToken();
User user =
new
User(username, userIp);
onLineUsers.put(username, user);
listModel.addElement(username);
}
}
else
if
(command.equals(
"MAX"
)) {
// 人数已达上限
textArea.append(stringTokenizer.nextToken()
+ stringTokenizer.nextToken() +
"\r\n"
);
closeCon();
// 被动的关闭连接
JOptionPane.showMessageDialog(frame,
"服务器缓冲区已满!"
,
"错误"
,
JOptionPane.ERROR_MESSAGE);
return
;
// 结束线程
}
else
{
// 普通消息
textArea.append(message +
"\r\n"
);
}
}
catch
(IOException e) {
e.printStackTrace();
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
}
}
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
最后此篇关于基于java编写局域网多人聊天室的文章就讲到这里了,如果你想了解更多关于基于java编写局域网多人聊天室的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在谈论 UDP 时,我看到/听到了几次拥塞。这是什么意思? 最佳答案 拥塞是指当您尝试在有限带宽上发送过多数据时,它发送数据的速度无法比传入数据快,因此会丢弃额外的数据包。 发生拥塞时,您可以看到这些
我想让 Xdebug 在办公室的 LAN 上以半安全的方式运行。我们当前的设置如下: 192.168.1.1 下 LAN 网络上的本地服务器与 Ubuntu Server 16 在 Ubuntu 服务
我是一名优秀的程序员,十分优秀!