JavaSocket实现多人聊天室
Java Socket实现多人聊天室---swing做UI
标签:socket聊天javaexception服务器string
2011-08-31 15:0620679人阅读评论(25)收藏举报分类:
java(21)
声明:本文为博主原创文章,未经博主允许不得。
今天翻硬盘的workspace发现一个Java Socket实现多人聊天室的源码,不记得是什么时候的事情了,貌似不是我写的。但写得还不错,
至少算个有模有样的聊天室工具。我简单的修改了一下,拿出来跟大家分享一下,仅供参考。。。
界面是用swing写的,还不懒,简约大方。有图有真相:
正如上图所示,这个程序分为服务器端和客户端,说白了就是两个main class,用eclipse 直接运行之。。。。。
聊天室的设计思想是:在局域网下,利用socket进行连接通信,当服务器端启动的时候,利用Thread线程不停的等待客户端的;当有客户端开启连
接的时候,服务器端通过IO流反馈“上线用户”信息给客户端,客户端也使用线程不停的接收服务器的信息,从而实现多人在线聊天功能。
程序中有三个类,分别Server.java(服务器端)、Client(客户端)、User.java(javabean)。代码如下:
Server.java(服务器端):
[html]view plaincopy
1.import java.awt.BorderLayout;
2.import java.awt.Color;
3.import java.awt.GridLayout;
4.import java.awt.Toolkit;
5.import java.awt.event.ActionEvent;
6.import java.awt.event.ActionListener;
7.import java.awt.event.WindowAdapter;
8.import java.awt.event.WindowEvent;
9.import java.io.BufferedReader;
10.import java.io.IOException;
11.import java.io.InputStreamReader;
12.import java.io.PrintWriter;
13.import https://www.360docs.net/doc/5e15028278.html,.BindException;
14.import https://www.360docs.net/doc/5e15028278.html,.ServerSocket;
15.import https://www.360docs.net/doc/5e15028278.html,.Socket;
16.import java.util.ArrayList;
17.import java.util.StringTokenizer;
18.
19.import javax.swing.DefaultListModel;
20.import javax.swing.JButton;
21.import javax.swing.JFrame;
22.import javax.swing.JLabel;
23.import javax.swing.JList;
24.import javax.swing.JOptionPane;
25.import javax.swing.JPanel;
26.import javax.swing.JScrollPane;
27.import javax.swing.JSplitPane;
28.import javax.swing.JTextArea;
29.import javax.swing.JTextField;
30.import javax.swing.border.TitledBorder;
31.
32.public class Server{
33.
34.private JFrame frame;
35.private JTextArea contentArea;
36.private JTextField txt_message;
37.private JTextField txt_max;
38.private JTextField txt_port;
39.private JButton btn_start;
40.private JButton btn_stop;
41.private JButton btn_send;
42.private JPanel northPanel;
43.private JPanel southPanel;
44.private JScrollPane rightPanel;
45.private JScrollPane leftPanel;
46.private JSplitPane centerSplit;
47.private JList userList;
48.private DefaultListModel listModel;
49.
50.private ServerSocket serverSocket;
51.private ServerThread serverThread;
52.private ArrayList
53.
54.private boolean isStart=false;
55.
56.//主方法,程序执行入口
57.public static void main(String[]args){
58.new Server();
59.}
60.
61.//执行消息发送
62.public void send(){
63.if(!isStart){
64.JOptionPane.showMessageDialog(frame,"服务器还未启动,不能发送消
息!","错误",
65.JOptionPane.ERROR_MESSAGE);
66.return;
67.}
68.if(clients.size()==0){
69.JOptionPane.showMessageDialog(frame,"没有用户在线,不能发送消
息!","错误",
70.JOptionPane.ERROR_MESSAGE);
71.return;
72.}
73.String message=txt_message.getText().trim();
74.if(message==null||message.equals("")){
75.JOptionPane.showMessageDialog(frame,"消息不能为空!","错误",
76.JOptionPane.ERROR_MESSAGE);
77.return;
78.}
79.sendServerMessage(message);//群发服务器消息
80.contentArea.append("服务器说:"+txt_message.getText()+"\r\n");
81.txt_message.setText(null);
82.}
83.
84.//构造放法
85.public Server(){
86.frame=new JFrame("服务器");
87.//更改JFrame的图标:
88.//frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.
getResource("qq.png")));
89.frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Server.class.g
etResource("qq.png")));
90.contentArea=new JTextArea();
91.contentArea.setEditable(false);
92.contentArea.setForeground(Color.blue);
93.txt_message=new JTextField();
94.txt_max=new JTextField("30");
95.txt_port=new JTextField("6666");
96.btn_start=new JButton("启动");
97.btn_stop=new JButton("停止");
98.btn_send=new JButton("发送");
99.btn_stop.setEnabled(false);
100.listModel=new DefaultListModel();
https://www.360docs.net/doc/5e15028278.html,erList=new JList(listModel);
102.
103.southPanel=new JPanel(new BorderLayout());
104.southPanel.setBorder(new TitledBorder("写消息"));
105.southPanel.add(txt_message,"Center");
106.southPanel.add(btn_send,"East");
107.leftPanel=new JScrollPane(userList);
108.leftPanel.setBorder(new TitledBorder("在线用户"));
109.
110.rightPanel=new JScrollPane(contentArea);
111.rightPanel.setBorder(new TitledBorder("消息显示区"));
112.
113.centerSplit=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftPanel, 114.rightPanel);
115.centerSplit.setDividerLocation(100);
116.northPanel=new JPanel();
117.northPanel.setLayout(new GridLayout(1,6));
118.northPanel.add(new JLabel("人数上限"));
119.northPanel.add(txt_max);
120.northPanel.add(new JLabel("端口"));
121.northPanel.add(txt_port);
122.northPanel.add(btn_start);
123.northPanel.add(btn_stop);
124.northPanel.setBorder(new TitledBorder("配置信息"));
125.
126.frame.setLayout(new BorderLayout());
127.frame.add(northPanel,"North");
128.frame.add(centerSplit,"Center");
129.frame.add(southPanel,"South");
130.frame.setSize(600,400);
131.//frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());//设置全屏132.int screen_width=Toolkit.getDefaultToolkit().getScreenSize().width; 133.int screen_height=Toolkit.getDefaultToolkit().getScreenSize().height;
134.frame.setLocation((screen_width-frame.getWidth())/2,
135.(screen_height-frame.getHeight())/2);
136.frame.setVisible(true);
137.
138.//关闭窗口时事件
139.frame.addWindowListener(new WindowAdapter(){
140.public void windowClosing(WindowEvent e){
141.if(isStart){
142.closeServer();//关闭服务器
143.}
144.System.exit(0);//退出程序
145.}
146.});
147.
148.//文本框按回车键时事件
149.txt_message.addActionListener(new ActionListener(){
150.public void actionPerformed(ActionEvent e){
151.send();
152.}
153.});
154.
155.//单击发送按钮时事件
156.btn_send.addActionListener(new ActionListener(){
157.public void actionPerformed(ActionEvent arg0){
158.send();
159.}
160.});
161.
162.//单击启动服务器按钮时事件
163.btn_start.addActionListener(new ActionListener(){
164.public void actionPerformed(ActionEvent e){
165.if(isStart){
166.JOptionPane.showMessageDialog(frame,"服务器已处于启动状态,不要重复启动!",
167."错误",JOptionPane.ERROR_MESSAGE);
168.return;
169.}
170.int max;
171.int port;
172.try{
173.try{
174.max=Integer.parseInt(txt_max.getText());
175.}catch(Exception e1){
176.throw new Exception("人数上限为正整数!");
177.}
178.if(max<=0){
179.throw new Exception("人数上限为正整数!");
180.}
181.try{
182.port=Integer.parseInt(txt_port.getText());
183.}catch(Exception e1){
184.throw new Exception("端口号为正整数!");
185.}
186.if(port<=0){
187.throw new Exception("端口号为正整数!");
188.}
189.serverStart(max,port);
190.contentArea.append("服务器已成功启动!人数上限:"+max+",端口:"+port
191.+"\r\n");
192.JOptionPane.showMessageDialog(frame,"服务器成功启动!"); 193.btn_start.setEnabled(false);
194.txt_max.setEnabled(false);
195.txt_port.setEnabled(false);
196.btn_stop.setEnabled(true);
197.}catch(Exception exc){
198.JOptionPane.showMessageDialog(frame,exc.getMessage(), 199."错误",JOptionPane.ERROR_MESSAGE);
200.}
201.}
202.});
203.
204.//单击停止服务器按钮时事件
205.btn_stop.addActionListener(new ActionListener(){
206.public void actionPerformed(ActionEvent e){
207.if(!isStart){
208.JOptionPane.showMessageDialog(frame,"服务器还未启动,无需停止!","错误",
209.JOptionPane.ERROR_MESSAGE);
210.return;
211.}
212.try{
213.closeServer();
214.btn_start.setEnabled(true);
215.txt_max.setEnabled(true);
216.txt_port.setEnabled(true);
217.btn_stop.setEnabled(false);
218.contentArea.append("服务器成功停止!\r\n");
219.JOptionPane.showMessageDialog(frame,"服务器成功停止!"); 220.}catch(Exception exc){
221.JOptionPane.showMessageDialog(frame,"停止服务器发生异常!
","错误",
222.JOptionPane.ERROR_MESSAGE);
223.}
224.}
225.});
226.}
227.
228.//启动服务器
229.public void serverStart(int max,int port)throws https://www.360docs.net/doc/5e15028278.html,.BindException{ 230.try{
231.clients=new ArrayList
232.serverSocket=new ServerSocket(port);
233.serverThread=new ServerThread(serverSocket,max);
234.serverThread.start();
235.isStart=true;
236.}catch(BindException e){
237.isStart=false;
238.throw new BindException("端口号已被占用,请换一个!");
239.}catch(Exception e1){
240.e1.printStackTrace();
241.isStart=false;
242.throw new BindException("启动服务器异常!");
243.}
244.}
245.
246.//关闭服务器
247.SuppressWarnings("deprecation")
248.public void closeServer(){
249.try{
250.if(serverThread!=null)
251.serverThread.stop();//停止服务器线程
252.
253.for(int i=clients.size()-1;i>=0;i--){
254.//给所有在线用户发送关闭命令
255.clients.get(i).getWriter().println("CLOSE");
256.clients.get(i).getWriter().flush();
257.//释放资源
258.clients.get(i).stop();//停止此条为客户端服务的线程
259.clients.get(i).reader.close();
260.clients.get(i).writer.close();
261.clients.get(i).socket.close();