功能:
登录
若用户账号不存在,弹出错误
若用户密码错误,弹出错误
若用户账号已在线,弹出错误
注册
若用户已注册,弹出错误
聊天室
多人聊天,类似QQ里的群。
点击右侧的在线用户,可进行一对一聊天。
一对一聊天
在聊天室中点击在线用户可进入此窗口。
发送消息后,对方会收到消息,并弹出一对一聊天窗口 。
说明:
服务端的IP和端口固定。(代码中使用127.0.0.1作为服务端的IP)
客户端通过该IP和端口访问服务器。
客户端向服务器发送消息,服务器根据消息做出不同的处理,并可能向其他客户端发送消息。
每个客户端都有一个客户端server进程,以接收服务端发来的消息。
初始化客户端时,启动客户端server进程,监听任意一个可用端口。用户登录时,将本地账户、密码、本地的server进程端口发给服务端,服务端检验用户合法性,若合 法,则更新该账户的IP地址和端口。以后服务端即可向该IP发送消息。
代码:
项目工程结构:
Server
1 package chatroomutil;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.PrintWriter;
6 import java.net.ServerSocket;
7 import java.net.Socket;
8
9 public abstract class Server {
10 protected ServerSocket sSocket;
11 public Server() {
12 }
13 protected int listen() {
14 while (true) {
15 Socket ots = null;
16 try {
17 ots = sSocket.accept();
18 } catch (IOException e) {
19 ChatRoomUtil.showErrorBox("服务器Accept错误");
20 System.exit(-1);
21 }
22 Thread hThread = new Thread(new handleThread(ots));
23 hThread.start();
24 }
25 }
26 // 处理消息的进程 的内部类
27 class handleThread implements Runnable {
28 Socket ots;
29 handleThread(Socket ots) {
30 this.ots = ots;
31 }
32 @Override
33 public void run() {
34 handleMessage(ots);
35 }
36 };
37 protected abstract String handle(Socket ots,String rMessage);//处理函数,输入收到的消息,返回要发送的消息
38 private String handleMessage(Socket ots) {
39 StringBuffer buffer=new StringBuffer();
40 BufferedReader reader=ChatRoomUtil.getMsgFromSocket(ots,buffer);//获取消息
41 String rMessage = buffer.toString();
42 String message=handle(ots,rMessage);//处理消息
43 PrintWriter writer=ChatRoomUtil.putMesgToSocket(ots, message);//发送消息
44 ChatRoomUtil.closeSocket(ots,reader,writer);//关闭
45 return null;
46 }
47 }
ChatRoomUtil
1 package chatroomutil;
2 import java.io.BufferedReader;
3 import java.io.IOException;
4 import java.io.InputStreamReader;
5 import java.io.PrintWriter;
6 import java.net.Socket;
7 import javax.swing.JOptionPane;
8
9 public class ChatRoomUtil {
10 public static String showErrorBox(String message) {//显示错误信息对话框
11 JOptionPane.showMessageDialog(null, message, "错误",
12 JOptionPane.ERROR_MESSAGE);
13 return message;
14 }
15 //获取消息
16 public static BufferedReader getMsgFromSocket(Socket socket,StringBuffer buffer){
17 BufferedReader reader = null;
18 try {
19 reader = new BufferedReader(
20 new InputStreamReader(socket.getInputStream()));
21 } catch (IOException e) {
22 ChatRoomUtil.showErrorBox("获取Socket输入流错误");
23 System.exit(-1);
24 }
25 try {
26 String line = "";
27 while ((line = reader.readLine()) != null) {
28 buffer.append(line + "\n");
29 }
30 buffer.deleteCharAt(buffer.length()-1);//去掉最后一个回车符
31 } catch (IOException e) {
32 ChatRoomUtil.showErrorBox("读取Socket输入流错误");
33 System.exit(-1);
34 }
35 try {
36 socket.shutdownInput();
37 } catch (IOException e) {
38 ChatRoomUtil.showErrorBox("关闭Socket输入时发生错误");
39 System.exit(-1);
40 }
41 return reader;
42 }
43 //发送消息
44 public static PrintWriter putMesgToSocket(Socket socket,String message){
45 PrintWriter writer = null;
46 try {
47 writer = new PrintWriter(socket.getOutputStream());
48 } catch (IOException e) {
49 ChatRoomUtil.showErrorBox("获取Socket输出流错误");
50 System.exit(-1);
51 }
52 writer.println(message);
53 writer.flush();
54 try {
55 socket.shutdownOutput();
56 } catch (IOException e1) {
57 ChatRoomUtil.showErrorBox("关闭Socket输出时发生错误");
58 System.exit(-1);
59 }
60 return writer;
61 }
62 //关闭socket、输入流、输出流
63 public static void closeSocket(Socket socket,BufferedReader reader,PrintWriter writer ){
64 try {
65 reader.close();
66 } catch (IOException e) {
67 ChatRoomUtil.showErrorBox("关闭Scoket输入流时发生错误");
68 System.exit(-1);
69 }
70 writer.close();
71 try {
72 socket.close();
73 } catch (IOException e) {
74 ChatRoomUtil.showErrorBox("关闭Scoket输出流时发生错误");
75 System.exit(-1);
76 }
77 }
78 }
ServerServer
1 package chatroomserver;
2 import java.io.BufferedReader;
3 import java.io.FileNotFoundException;
4 import java.io.FileReader;
5 import java.io.IOException;
6 import java.io.RandomAccessFile;
7 import java.net.ServerSocket;
8 import java.net.Socket;
9 import java.util.Enumeration;
10 import java.util.Hashtable;
11 import chatroomsend.Send;
12 import chatroomutil.ChatRoomUtil;
13 import chatroomutil.Server;
14
15 public class ServerServer extends Server {
16 Hashtable<String, User> onlineTable = new Hashtable<String, User>();// 在线用户集合
17 Hashtable<String, User> offlineTable = new Hashtable<String, User>();// 离线用户集合
18 // 用户内部类
19 class User {
20 String id;
21 String pwd;
22 String IP;
23 int port;
24 User(String id, String pwd) {
25 this.id = id;
26 this.pwd = pwd;
27 }
28 }
29 // 发送进程内部类
30 class sendThread implements Runnable {
31 String mesg;
32 String IP;
33 int port;
34 sendThread(String IP, int port, String mesg) {
35 this.IP = IP;
36 this.port = port;
37 this.mesg = mesg;
38 }
39 @Override
40 public void run() {
41 Send sendClient = new Send();
42 sendClient.connect(IP, port, 1000);
43 sendClient.send(mesg);
44 }
45 };
46 public ServerServer(int port) throws IOException {
47 init(port);
48 initUsers();
49 listen();
50 }
51 private int init(int port) throws IOException {
52 try {
53 sSocket = new ServerSocket(port);//绑定指定端口
54 } catch (IOException e) {
55 ChatRoomUtil.showErrorBox("服务器初始化失败,无法绑定端口。");
56 System.exit(-1);
57 }
58 return port;
59 }
60 private int initUsers() {//读取Users文件,初始化offlineTable
61 BufferedReader reader = null;
62 try {
63 reader = new BufferedReader(new FileReader("Users.txt"));
64 } catch (FileNotFoundException e1) {
65 ChatRoomUtil.showErrorBox("无法找到User文件");
66 System.exit(-1);
67 }
68 String line;
69 String[] fa;
70 try {
71 while ((line = reader.readLine()) != null) {
72 fa = line.split(":", 2);
73 User f = new User(fa[0], fa[1]);
74 offlineTable.put(fa[0], f);
75 }
76 reader.close();
77 } catch (IOException e) {
78 ChatRoomUtil.showErrorBox("读取User文件错误");
79 System.exit(-1);
80 }
81 return 0;
82 }
83 private int saveNewUser(String id, String pwd) {//将新用户写入Users文件最后
84 try {
85 RandomAccessFile file = new RandomAccessFile("Users.txt", "rw");
86 file.seek(file.length());
87 file.writeBytes(id + ":" + pwd + "\r\n");
88 file.close();
89 } catch (FileNotFoundException e) {
90 ChatRoomUtil.showErrorBox("写入User文件错误");
91 System.exit(-1);
92 } catch (IOException e) {
93 ChatRoomUtil.showErrorBox("写入User文件错误");
94 System.exit(-1);
95 }
96 return 0;
97 }
98 String loginCheck(String id, String pwd, String IP, int port) {//检查登录用户的合法性
99 System.out.println("logi check");
100 if (onlineTable.containsKey(id))
101 return "alreadyonline";//该用户已在线
102 User f = offlineTable.get(id);
103 if (f == null)
104 return "nothisid";//无此用户
105 if (f.pwd.compareTo(pwd) == 0) {
106 oneUserOnline(id, IP, port);
107 sendOnlinesToNewOnlineUser(id, IP, port);
108 sendNewOnlineUserToOnlines(id);
109 return "yes";//合法
110 } else {
111 return "wrong";//密码错误
112 }
113 }
114 int oneUserOnline(String id, String IP, int port) {//一个新用户上线
115 User f = offlineTable.get(id);
116 offlineTable.remove(id);
117 onlineTable.put(id, f);
118 f.IP = IP;
119 f.port = port;
120 return 0;
121 }
122 int sendNewOnlineUserToOnlines(String id) {//给所有在线用户发送新上线的用户的id
123 Enumeration<User> fs = onlineTable.elements();
124 while (fs.hasMoreElements()) {
125 User f = fs.nextElement();
126 if (f.id.compareTo(id) != 0) {
127 Thread hThread = new Thread(
128 new sendThread(f.IP, f.port, "newf" + id));
129 hThread.start();
130 }
131 }
132 return 0;
133 }
134 int sendMesg(String mesg) {//向所有在线用户转发一条消息
135 Enumeration<User> fs = onlineTable.elements();
136 while (fs.hasMoreElements()) {
137 User f = fs.nextElement();
138 Thread hThread = new Thread(
139 new sendThread(f.IP, f.port, "mesg" + mesg));
140 hThread.start();
141 }
142 return 0;
143 }
144 int sendChat(String id, String mesg) {//向一个用户发送一条一对一聊天的消息
145 User f = onlineTable.get(id);
146 Thread hThread = new Thread(
147 new sendThread(f.IP, f.port, "chat" + mesg));
148 hThread.start();
149 return 0;
150 }
151 String newRegisUser(String id, String pwd) {//有新注册的用户
152 if (onlineTable.containsKey(id) || offlineTable.containsKey(id)) {
153 return "no";
154 }
155 offlineTable.put(id, new User(id, pwd));
156 saveNewUser(id, pwd);
157 return "yes";
158 }
159 int sendOnlinesToNewOnlineUser(String id, String IP, int port) {//给新上线的用户发送所有已在线用户的id
160 if (onlineTable.isEmpty() || onlineTable.size() == 1) {
161 return 0;
162 }
163 StringBuffer strBuf = new StringBuffer();
164 Enumeration<User> fs = onlineTable.elements();
165 while (fs.hasMoreElements()) {
166 User f = fs.nextElement();
167 if (f.id.compareTo(id) != 0) {
168 strBuf.append(f.id);
169 strBuf.append(";");
170 }
171 }
172 String str = strBuf.toString();
173 Thread hThread = new Thread(new sendThread(IP, port, "newf" + str));
174 hThread.start();
175 return 0;
176 }
177 int oneUserOffline(String id) {//有一个用户下线,将其下线消息发送给所有在线用户
178 Enumeration<User> fs = onlineTable.elements();
179 while (fs.hasMoreElements()) {
180 User f = fs.nextElement();
181 if (f.id.compareTo(id) == 0) {
182 onlineTable.remove(id);
183 offlineTable.put(id, f);
184 } else {
185 Thread hThread = new Thread(
186 new sendThread(f.IP, f.port, "offl" + id));
187 hThread.start();
188 }
189 }
190 return 0;
191 }
192 protected String handle(Socket ots,String rMessage){
193 System.out.println("handle");
194 if (rMessage.startsWith("regi")) {//注册
195 rMessage = rMessage.substring("regi".length());
196 String id = rMessage.substring(0, rMessage.indexOf(','));
197 String pwd = rMessage.substring(rMessage.indexOf(',') + 1);
198 return newRegisUser(id, pwd);
199 }
200 if (rMessage.startsWith("logi")) {//登录
201 System.out.println("logi");
202 rMessage = rMessage.substring("logi".length());
203 String id = rMessage.substring(0, rMessage.indexOf(','));
204 String pwd = rMessage.substring(rMessage.indexOf(',') + 1,
205 rMessage.lastIndexOf(','));
206 String portstr = rMessage.substring(rMessage.lastIndexOf(',') + 1);
207 int port = new Integer(portstr);
208 String IP = ots.getInetAddress().getHostAddress();
209 return loginCheck(id, pwd, IP, port);
210 }
211 if (rMessage.startsWith("mesg")) {//聊天室消息
212 String mesg = rMessage.substring(("mesg").length());
213 sendMesg(mesg);
214 return "getm";
215 }
216 if (rMessage.startsWith("chat")) {//一对一消息
217 String chat = rMessage.substring(("chat").length());
218 String id = chat.substring(0, chat.indexOf(':'));
219 String mesg = chat.substring(chat.indexOf(':') + 1);
220 sendChat(id, mesg);
221 return "getm";
222 }
223 if (rMessage.startsWith("offl")) {//下线
224 String id = rMessage.substring(("offl").length());
225 oneUserOffline(id);
226 return "getm";
227 }
228 return "getm";
229 }
230
231 public static void main(String[] args) {
232 try {
233 new ServerServer(65142);
234 } catch (IOException e) {
235 e.printStackTrace();
236 }
237 }
238 }
Send
1 package chatroomsend;
2 import java.io.BufferedReader;
3 import java.io.IOException;
4 import java.io.PrintWriter;
5 import java.net.InetSocketAddress;
6 import java.net.Socket;
7 import chatroomutil.ChatRoomUtil;
8
9 public class Send {
10 Socket socket;
11 public Send() {
12 super();
13 socket = new Socket();
14 }
15 public int connect(String IP, int port, int timeout) {//连接
16 try {
17 socket.connect(new InetSocketAddress(IP, port), timeout);
18 } catch (IOException e) {
19 return -1;
20 }
21 return 0;
22 }
23 public String send(String message) {
24 PrintWriter writer=ChatRoomUtil.putMesgToSocket(socket, message);
25 StringBuffer buffer=new StringBuffer();
26 BufferedReader reader=ChatRoomUtil.getMsgFromSocket(socket,buffer);
27 String rMessage = buffer.toString();
28 ChatRoomUtil.closeSocket(socket,reader,writer);
29 return rMessage;
30 }
31 }
LoginBox
1 package chatroomclient;
2 import java.awt.*;
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.awt.event.MouseEvent;
6 import java.awt.event.MouseListener;
7 import java.io.IOException;
8 import javax.swing.*;
9 import chatroomsend.Send;
10 import chatroomutil.ChatRoomUtil;
11
12 public class LoginBox extends JFrame implements ActionListener, MouseListener {
13 private static final long serialVersionUID = -329711894663212488L;
14 ClientServer myServer;
15 String serverIP;
16 int serverPort;
17 JLabel l_account = new JLabel();
18 JLabel l_password = new JLabel();
19 JLabel l_regist = new JLabel();
20 JTextField j_account = new JTextField();
21 JPasswordField j_password = new JPasswordField();
22 JButton submit = new JButton();
23 JButton cancel = new JButton();
24 JLabel clearAccount = new JLabel();
25 JLabel clearPassword = new JLabel();
26 public LoginBox(String ip, int port) {
27 super("登录");
28 try {
29 myServer = new ClientServer(serverIP, serverPort);
30 Thread myServerThread = new Thread(myServer);
31 myServerThread.start();
32 } catch (IOException e) {
33 ChatRoomUtil.showErrorBox("服务器进程初始化失败,无法绑定端口。");
34 System.exit(-1);
35 }
36 serverIP = ip;
37 serverPort = port;
38 setLayout(null);
39 l_account.setVisible(true);
40 l_account.setBounds(80, 40, 50, 30);
41 l_account.setText("账号:");
42 l_password.setVisible(true);
43 l_password.setBounds(80, 80, 50, 30);
44 l_password.setText("密码:");
45 j_account.setBounds(130, 40, 150, 30);
46 j_password.setBounds(130, 80, 150, 30);
47 clearAccount.setBounds(280, 42, 26, 26);
48 clearPassword.setBounds(280, 82, 26, 26);
49 submit.setBounds(100, 130, 80, 30);
50 submit.setText("登录");
51 cancel.setText("取消");
52 clearAccount.setText("X");
53 clearPassword.setText("X");
54 clearAccount.setOpaque(true);
55 clearPassword.setOpaque(true);
56 clearAccount.setBackground(Color.LIGHT_GRAY);
57 clearPassword.setBackground(Color.LIGHT_GRAY);
58 clearAccount.setHorizontalAlignment(JLabel.CENTER);
59 clearPassword.setHorizontalAlignment(JLabel.CENTER);
60 submit.setBackground(Color.LIGHT_GRAY);
61 cancel.setBackground(Color.LIGHT_GRAY);
62 submit.addActionListener(this);
63 cancel.addActionListener(this);
64 cancel.setBounds(190, 130, 80, 30);
65 l_regist.setBounds(270, 200, 70, 30);
66 l_regist.setText("没有账号?");
67 this.add(l_account);
68 this.add(l_password);
69 this.add(j_account);
70 this.add(j_password);
71 this.add(submit);
72 this.add(cancel);
73 this.add(l_regist);
74 this.add(clearAccount);
75 this.add(clearPassword);
76 setBounds(480, 240, 370, 270);
77 setVisible(true);
78 setResizable(false);
79 this.setDefaultCloseOperation(EXIT_ON_CLOSE);
80 validate();
81 l_regist.addMouseListener(this);
82 clearAccount.addMouseListener(this);
83 clearPassword.addMouseListener(this);
84 }
85 String checkPwd(String id, String pwd) {
86 Send sendClient = new Send();
87 sendClient.connect(serverIP, serverPort, 1000);
88 String ret= sendClient
89 .send("logi" + id + "," + pwd + "," + myServer.getMyServerPort());
90 if (ret.compareTo("yes") == 0) {
91 myServer.chatRoom = new ChatRoom(id, serverIP, serverPort);
92 dispose();
93 } else if (ret.compareTo("wrong") == 0) {
94 ChatRoomUtil.showErrorBox("登录失败,密码有误。");
95 } else if (ret.compareTo("alreadyonline") == 0) {
96 ChatRoomUtil.showErrorBox("登录失败,该账号已在线");
97 } else if (ret.compareTo("nothisid") == 0) {
98 ChatRoomUtil.showErrorBox("登录失败,账号不存在。");
99 new RegisBox(serverIP, serverPort,
100 myServer.getMyServerPort());
101 }
102 return ret;
103 }
104 @Override
105 public void actionPerformed(ActionEvent e) {
106 Object t = e.getSource();
107 if (e.getSource().getClass() == JButton.class) {
108 JButton button = (JButton) (t);
109 if (button.getText().compareTo("登录") == 0) {
110 String id = j_account.getText();
111 String pwd = String.valueOf(j_password.getPassword());
112 if (id.compareTo("") == 0 || pwd.compareTo("") == 0) {
113 ChatRoomUtil.showErrorBox("账号与密码均不能为空");
114 return;
115 }
116 checkPwd(id, pwd);
117 }
118 if (button.getText().compareTo("取消") == 0) {
119 dispose();
120 System.exit(0);
121 }
122 }
123 }
124 @Override
125 public void mouseClicked(MouseEvent e) {
126 if (e.getSource().equals(l_regist)) {
127 new RegisBox(serverIP, serverPort,
128 myServer.getMyServerPort());
129 }
130 if (e.getSource().equals(clearAccount)) {
131 j_account.setText("");
132 }
133 if (e.getSource().equals(clearPassword)) {
134 j_password.setText("");
135 }
136 }
137 @Override
138 public void mousePressed(MouseEvent e) {
139 }
140 @Override
141 public void mouseReleased(MouseEvent e) {
142 }
143
144 @Override
145 public void mouseEntered(MouseEvent e) {
146 Object x = e.getSource();
147 if (x.equals(l_regist)) {
148 JLabel l = (JLabel) x;
149 l.setForeground(Color.blue);
150 }
151 if (x.equals(clearAccount) || x.equals(clearPassword)) {
152 JLabel l = (JLabel) x;
153 l.setBackground(Color.GRAY);
154 }
155 }
156
157 @Override
158 public void mouseExited(MouseEvent e) {
159 Object x = e.getSource();
160 if (x.equals(l_regist)) {
161 JLabel l = (JLabel) x;
162 l.setForeground(Color.BLACK);
163 }
164 if (x.equals(clearAccount) || x.equals(clearPassword)) {
165 JLabel l = (JLabel) x;
166 l.setBackground(Color.LIGHT_GRAY);
167 }
168 }
169 public static void main(String[] args) {
170 String serverIP = "127.0.0.1";
171 int serverPort = 65142;
172 new LoginBox(serverIP, serverPort);
173 }
174 }
RegisBox
1 package chatroomclient;
2 import java.awt.*;
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import javax.swing.*;
6 import chatroomsend.Send;
7 import chatroomutil.ChatRoomUtil;
8 public class RegisBox extends JFrame implements ActionListener {
9 private static final long serialVersionUID = 5795626909275119718L;
10 String serverIP;
11 int serverPort;
12 int myServerPort;
13 JLabel id_label = new JLabel();
14 JLabel pwd_label = new JLabel();
15 JLabel pwdCheck_label = new JLabel();
16 JLabel num_label = new JLabel();
17 JLabel firstName_label = new JLabel();
18 JLabel lastName_label = new JLabel();
19 JLabel age_label = new JLabel();
20 JLabel sex_label = new JLabel();
21 JTextField id_text = new JTextField();
22 JPasswordField pwd_text = new JPasswordField();
23 JPasswordField pwdCheck_text = new JPasswordField();
24 JTextField num_text = new JTextField();
25 JTextField firstName_text = new JTextField();
26 JTextField lastName_text = new JTextField();
27 JTextField age_text = new JTextField();
28 JComboBox sex_box = new JComboBox();
29 JButton cancel = new JButton();
30 JButton regis = new JButton();
31 public RegisBox(String serverIP, int serverPort, int myServerPort) {
32 super();
33 this.serverIP = serverIP;
34 this.serverPort = serverPort;
35 this.myServerPort = myServerPort;
36 setLayout(null);
37 setTitle("注册");
38 id_label.setBounds(60, 23, 50, 20);
39 pwd_label.setBounds(60, 53, 50, 20);
40 pwdCheck_label.setBounds(50, 83, 70, 20);
41 num_label.setBounds(60, 113, 50, 20);
42 firstName_label.setBounds(60, 143, 50, 20);
43 lastName_label.setBounds(60, 173, 50, 20);
44 age_label.setBounds(60, 203, 50, 20);
45 sex_label.setBounds(60, 233, 50, 20);
46 id_text.setBounds(130, 20, 200, 26);
47 pwd_text.setBounds(130, 50, 200, 26);
48 pwdCheck_text.setBounds(130, 80, 200, 26);
49 num_text.setBounds(130, 110, 200, 26);
50 firstName_text.setBounds(130, 140, 200, 26);
51 lastName_text.setBounds(130, 170, 200, 26);
52 age_text.setBounds(130, 200, 200, 26);
53 sex_box.setBounds(130, 230, 200, 26);
54 regis.setBounds(190, 270, 70, 30);
55 cancel.setBounds(270, 270, 70, 30);
56 id_label.setText("账号");
57 pwd_label.setText("密码");
58 pwdCheck_label.setText("密码确认");
59 num_label.setText("编号");
60 firstName_label.setText("名");
61 lastName_label.setText("姓");
62 age_label.setText("年龄");
63 sex_label.setText("性别");
64 sex_box.addItem("男");
65 sex_box.addItem("女");
66 regis.setText("提交");
67 cancel.setText("取消");
68 regis.setBackground(Color.LIGHT_GRAY);
69 cancel.setBackground(Color.LIGHT_GRAY);
70 sex_box.setBackground(Color.LIGHT_GRAY);
71 regis.addActionListener(this);
72 cancel.addActionListener(this);
73 this.add(id_label);
74 this.add(pwd_label);
75 this.add(pwdCheck_label);
76 this.add(num_label);
77 this.add(firstName_label);
78 this.add(lastName_label);
79 this.add(age_label);
80 this.add(sex_label);
81 this.add(id_text);
82 this.add(pwd_text);
83 this.add(pwdCheck_text);
84 this.add(num_text);
85 this.add(firstName_text);
86 this.add(lastName_text);
87 this.add(age_text);
88 this.add(sex_box);
89 this.add(regis);
90 this.add(cancel);
91 setBounds(200, 200, 500, 400);
92 validate();
93 setResizable(false);
94 setVisible(true);
95 }
96 boolean regis(String serverIP, int serverPort, String id, String pwd,
97 int myServerPort) {
98 Send sendClient = new Send();
99 sendClient.connect(serverIP, serverPort, 1000);
100 if (sendClient.send("regi" + id + "," + pwd).compareTo("yes") == 0) {
101 return true;
102 }
103 return false;
104 }
105 boolean check() {
106 String id = id_text.getText();
107 String pwd = String.valueOf(pwd_text.getPassword());
108 String pwdc = String.valueOf(pwdCheck_text.getPassword());
109 String fName = firstName_text.getText();
110 String lName = lastName_text.getText();
111 String age = age_text.getText();
112 String num = num_text.getText();
113 String sex = sex_box.getSelectedItem().toString();
114 if (id.compareTo("") == 0) {
115 ChatRoomUtil.showErrorBox("账号不能为空");
116 return false;
117 }
118 if (pwd.compareTo("") == 0) {
119 ChatRoomUtil.showErrorBox("密码不能为空");
120 return false;
121 }
122 if (pwdc.compareTo("") == 0) {
123 ChatRoomUtil.showErrorBox("请确认密码");
124 return false;
125 }
126 if (pwd.compareTo(pwdc) != 0) {
127 ChatRoomUtil.showErrorBox("两次输入的密码不符");
128 return false;
129 }
130 if (num.compareTo("") == 0) {
131 ChatRoomUtil.showErrorBox("编号不能为空");
132 return false;
133 }
134 if (fName.compareTo("") == 0) {
135 ChatRoomUtil.showErrorBox("名不能为空");
136 return false;
137 }
138 if (lName.compareTo("") == 0) {
139 ChatRoomUtil.showErrorBox("姓不能为空");
140 return false;
141 }
142 if (age.compareTo("") == 0) {
143 ChatRoomUtil.showErrorBox("年龄不能为空");
144 return false;
145 }
146 if (sex.compareTo("") == 0) {
147 ChatRoomUtil.showErrorBox("性别不能为空");
148 return false;
149 }
150 if (regis(serverIP, serverPort, id, pwd, myServerPort)) {
151 dispose();
152 } else {
153 ChatRoomUtil.showErrorBox("注册失败。该用户已存在");
154 return false;
155 }
156 return true;
157 }
158 @Override
159 public void actionPerformed(ActionEvent e) {
160 Object t = e.getSource();
161 if (e.getSource().getClass() == JButton.class) {
162 JButton button = (JButton) (t);
163 if (button.getText().compareTo("提交") == 0) {
164 check();
165 }
166 if (button.getText().compareTo("取消") == 0) {
167 dispose();
168 }
169 }
170 }
171 }
ClientServer
1 package chatroomclient;
2 import java.io.IOException;
3 import java.net.ServerSocket;
4 import java.net.Socket;
5 import chatroomutil.ChatRoomUtil;
6 import chatroomutil.Server;
7
8 public class ClientServer extends Server implements Runnable {
9 ChatRoom chatRoom;
10 private int myPort;
11 public ClientServer(String serverIP, int serverPort) throws IOException {
12 super();
13 myPort = init();
14 }
15 int getMyServerPort() {
16 return myPort;
17 }
18 private int createServerSocket(int i) throws IOException {//绑定端口i
19 if (i >= 65536) {
20 ChatRoomUtil.showErrorBox("ClientServer无端口可绑定");
21 System.exit(-1);
22 }
23 try {
24 sSocket = new ServerSocket(i);
25 } catch (IOException e) {
26 return createServerSocket(i + 1);
27 }
28 return i;
29 }
30 private int init() throws IOException {
31 int port = createServerSocket(1025);
32 return port;
33 }
34 @Override
35 protected String handle(Socket ots,String rMessage){
36 String message = "getm";
37 if (rMessage.startsWith("newf")) {
38 while (chatRoom == null) {
39 try {
40 Thread.sleep(300);
41 } catch (InterruptedException e) {
42 ChatRoomUtil.showErrorBox("ClientServer在Sleep时出错");
43 System.exit(-1);
44 }
45 }
46 String ids = rMessage.substring(("newf").length());
47 String[] idArray = ids.split(";");
48 chatRoom.addFriend(idArray);
49 }
50 if (rMessage.startsWith("offl")) {
51 String name = rMessage.substring(("offl").length());
52 chatRoom.removeFriend(name);
53 }
54 if (rMessage.startsWith("mesg")) {
55 String mesg = rMessage.substring(("mesg").length());
56 chatRoom.addRecord(mesg);
57 }
58 if (rMessage.startsWith("chat")) {
59 String chat = rMessage.substring(("chat").length());
60 String id = chat.substring(0, chat.indexOf(':'));
61 String mesg = chat.substring(chat.indexOf(':') + 1);
62 chatRoom.dialogAddRecord(id, mesg);
63 }
64 return message;
65 }
66 @Override
67 public void run() {
68 listen();
69 }
70 }
ChatRoom
1 package chatroomclient;
2 import java.awt.*;
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.awt.event.MouseEvent;
6 import java.awt.event.MouseListener;
7 import java.awt.event.WindowAdapter;
8 import java.awt.event.WindowEvent;
9 import java.util.HashSet;
10 import java.util.Hashtable;
11 import java.util.Iterator;
12 import java.util.TimerTask;
13 import javax.swing.*;
14 import javax.swing.event.CaretEvent;
15 import javax.swing.event.CaretListener;
16 import chatroomsend.Send;
17 import chatroomutil.ChatRoomUtil;
18
19 public class ChatRoom extends JFrame implements ActionListener, MouseListener {
20 private static final long serialVersionUID = -9016166784223701159L;
21 String myId;
22 String serverIP;
23 int serverPort;
24 JLabel chatRoomLabel = new JLabel();
25 JLabel onlineLabel = new JLabel();
26 JTextArea chatArea = new JTextArea();
27 JPanel onlineArea = new JPanel();
28 JTextArea sendArea = new JTextArea(5, 20);
29 JButton sendButton = new JButton();
30 JScrollPane chatScroll = new JScrollPane(chatArea);
31 JScrollPane onlineScroll = new JScrollPane(onlineArea);
32 JScrollPane sendScroll = new JScrollPane(sendArea);
33 JPanel chatPanel = new JPanel();
34 JPanel onlinePanel = new JPanel();
35 JPanel sendPanel = new JPanel();
36 JPanel chatAndOnlinePanel = new JPanel();
37 HashSet<String> friends = new HashSet<String>();
38 Hashtable<String, ChatDialog> chatDialogs = new Hashtable<String, ChatDialog>();
39 BorderLayout mainLayout = new BorderLayout();
40 BorderLayout chatLayout = new BorderLayout();
41 BorderLayout onlineLayout = new BorderLayout();
42 BorderLayout sendLayout = new BorderLayout();
43 BorderLayout chatAndOnlineLayout = new BorderLayout();
44 FlowLayout onlineAreaLayout = new FlowLayout();
45 public ChatRoom(String id, String serverIP, int port) {
46 super("聊天室 " + id);
47 this.myId = id;
48 this.serverIP = serverIP;
49 this.serverPort = port;
50 mainLayout.setVgap(5);
51 sendLayout.setHgap(10);
52 chatAndOnlineLayout.setHgap(15);
53 onlineAreaLayout.setVgap(1);
54 this.setLayout(mainLayout);
55 chatPanel.setLayout(chatLayout);
56 onlinePanel.setLayout(onlineLayout);
57 sendPanel.setLayout(sendLayout);
58 chatAndOnlinePanel.setLayout(chatAndOnlineLayout);
59 chatArea.setLineWrap(true);
60 sendArea.setLineWrap(true);
61 onlineArea.setLayout(onlineAreaLayout);
62 onlineArea.setPreferredSize(new Dimension(130, 200));
63 sendButton.setText(" 发送 ");
64 sendButton.setBackground(Color.LIGHT_GRAY);
65 sendButton.addActionListener(this);
66 onlineLabel.setText("在线好友(点击可开始聊天)");
67 chatRoomLabel.setText("聊天");
68 chatArea.setEditable(false);
69 chatArea.setBackground(new Color(230, 230, 230));
70 chatPanel.add(chatRoomLabel, BorderLayout.NORTH);
71 chatPanel.add(chatScroll, BorderLayout.CENTER);
72 onlinePanel.add(onlineLabel, BorderLayout.NORTH);
73 onlinePanel.add(onlineScroll, BorderLayout.CENTER);
74 sendPanel.add(sendScroll, BorderLayout.CENTER);
75 sendPanel.add(sendButton, BorderLayout.EAST);
76 chatAndOnlinePanel.add(chatPanel, BorderLayout.CENTER);
77 chatAndOnlinePanel.add(onlinePanel, BorderLayout.EAST);
78 this.add(sendPanel, BorderLayout.SOUTH);
79 this.add(chatAndOnlinePanel, BorderLayout.CENTER);
80 friends.add(myId);
81 this.setBounds(200, 200, 600, 650);
82 setVisible(true);
83 reFreshOnlineArea();
84 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
85 this.addWindowListener(new WindowAdapter() {
86 public void windowClosing(WindowEvent e) {//点击关闭按钮时发送下线消息
87 sendOffLine();
88 System.exit(0);
89 }
90 });
91 sendArea.addCaretListener(new CaretListener() {
92 @Override
93 public void caretUpdate(CaretEvent e) {
94 String str = sendArea.getText();
95 if (str.length() > 5000) {
96 ChatRoomUtil.showErrorBox("字数过多,超出限制。");
97 }
98 }
99 });
100 new java.util.Timer().schedule(new TimerTask() {//定时刷新界面
101 public void run() {
102 repaint();
103 }
104 }, 400, 400);
105 }
106 int reFreshOnlineArea() {//刷新当前在线用户
107 int size = friends.size();
108 onlineArea.removeAll();
109 Iterator<String> it = friends.iterator();
110 while (it.hasNext()) {
111 String str = it.next();
112 String id = str;
113 JLabel label = new JLabel(id);
114 label.addMouseListener(this);
115 label.setPreferredSize(new Dimension(130, 20));
116 label.setBackground(Color.GRAY);
117 label.setForeground(Color.WHITE);
118 label.setHorizontalAlignment(JLabel.CENTER);
119 label.setOpaque(true);
120 onlineArea.add(label);
121 }
122 onlineArea.setPreferredSize(new Dimension(130, size * 22));
123 this.repaint();
124 this.validate();
125 return 0;
126 }
127 int sendOffLine() {//发送下线消息
128 Send sendClient = new Send();
129 sendClient.connect(serverIP, serverPort, 1000);
130 sendClient.send("offl" + myId);
131 return 0;
132 }
133 public int addFriend(String[] fs) {//添加上线的用户
134 for (int i = 0; i < fs.length; i++) {
135 friends.add(fs[i]);
136 }
137 reFreshOnlineArea();
138 return 0;
139 }
140 public int removeFriend(String friendID) {//移除一个用户(已下线)
141 friends.remove(friendID);
142 reFreshOnlineArea();
143 return 0;
144 }
145 public int addRecord(String mesg) {//添加聊天记录
146 chatArea.append(mesg + "\n");
147 chatArea.setCaretPosition(chatArea.getText().length());
148 this.validate();
149 return 0;
150 }
151 public int dialogAddRecord(String id, String mesg) {//给一对一聊天增加聊天记录
152 if (chatDialogs.containsKey(id) == false) {
153 chatDialogs.put(id,
154 new ChatDialog(this, myId, id, serverIP, serverPort));
155 }
156 chatDialogs.get(id).addRecord(mesg);
157 return 0;
158 }
159 int removeDialog(String id) {//移除一对一聊天
160 chatDialogs.remove(id);
161 return 0;
162 }
163 private String sendMessage(String mesg) {//发送群聊消息
164 Send sendClient = new Send();
165 sendClient.connect(serverIP, serverPort, 1000);
166 String getm = sendClient.send("mesg" + myId + ": \n" + mesg);
167 return getm;
168 }
169 @Override
170 public void actionPerformed(ActionEvent e) {
171 if (e.getSource().getClass() == JButton.class) {
172 sendMessage(sendArea.getText());
173 sendArea.setText("");
174 }
175 }
176 @Override
177 public void mouseClicked(MouseEvent e) {
178 if (e.getSource().getClass() == JLabel.class) {
179 JLabel l = (JLabel) e.getSource();
180 if (l.getText().compareTo(myId) == 0) {
181 return;
182 }
183 if (chatDialogs.containsKey(l.getText())) {
184 return;
185 }
186 chatDialogs.put(l.getText(), new ChatDialog(this, myId, l.getText(),
187 serverIP, serverPort));
188 }
189 }
190 @Override
191 public void mouseEntered(MouseEvent e) {
192 if (e.getSource().getClass() == JLabel.class) {
193 JLabel l = (JLabel) e.getSource();
194 l.setBackground(Color.LIGHT_GRAY);
195 l.setForeground(Color.BLACK);
196 }
197 }
198 @Override
199 public void mouseExited(MouseEvent e) {
200 if (e.getSource().getClass() == JLabel.class) {
201 JLabel l = (JLabel) e.getSource();
202 l.setBackground(Color.GRAY);
203 l.setForeground(Color.WHITE);
204 }
205 }
206 @Override
207 public void mousePressed(MouseEvent e) {
208 }
209 @Override
210 public void mouseReleased(MouseEvent e) {
211 }
212 }
ChatDialog
1 package chatroomclient;
2 import java.awt.*;
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.awt.event.WindowAdapter;
6 import java.awt.event.WindowEvent;
7 import java.util.HashSet;
8 import java.util.TimerTask;
9 import javax.swing.*;
10 import javax.swing.event.CaretEvent;
11 import javax.swing.event.CaretListener;
12 import chatroomsend.Send;
13 import chatroomutil.ChatRoomUtil;
14
15 public class ChatDialog extends JFrame implements ActionListener {
16 private static final long serialVersionUID = 1437996471885472344L;
17 String myId;
18 String otsId;
19 String serverIP;
20 int serverPort;
21 JLabel chatRoomLabel = new JLabel();
22 JTextArea chatArea = new JTextArea();
23 JTextArea sendArea = new JTextArea(5, 20);
24 JButton sendButton = new JButton();
25 JScrollPane chatScroll = new JScrollPane(chatArea);
26 JScrollPane sendScroll = new JScrollPane(sendArea);
27 JPanel chatPanel = new JPanel();
28 JPanel sendPanel = new JPanel();
29 HashSet<String> friends = new HashSet<String>();
30 BorderLayout mainLayout = new BorderLayout();
31 BorderLayout chatLayout = new BorderLayout();
32 BorderLayout sendLayout = new BorderLayout();
33 ChatRoom chatRoom;
34 public ChatDialog(final ChatRoom chatRoom, String id, final String otsId,
35 String serverIP, int port) {
36 super(id + "与" + otsId + "聊天");
37 this.chatRoom = chatRoom;
38 this.myId = id;
39 this.otsId = otsId;
40 this.serverIP = serverIP;
41 this.serverPort = port;
42 mainLayout.setVgap(5);
43 sendLayout.setHgap(10);
44 this.setLayout(mainLayout);
45 chatPanel.setLayout(chatLayout);
46 sendPanel.setLayout(sendLayout);
47 chatArea.setLineWrap(true);
48 sendArea.setLineWrap(true);
49 sendButton.setText(" 发送 ");
50 sendButton.setBackground(Color.LIGHT_GRAY);
51 sendButton.addActionListener(this);
52 chatRoomLabel.setText("聊天");
53 chatArea.setEditable(false);
54 chatArea.setBackground(new Color(230, 230, 230));
55 chatPanel.add(chatRoomLabel, BorderLayout.NORTH);
56 chatPanel.add(chatScroll, BorderLayout.CENTER);
57 sendPanel.add(sendScroll, BorderLayout.CENTER);
58 sendPanel.add(sendButton, BorderLayout.EAST);
59 this.add(sendPanel, BorderLayout.SOUTH);
60 this.add(chatPanel, BorderLayout.CENTER);
61 this.setBounds(200, 200, 530, 600);
62 setVisible(true);
63 this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
64 sendArea.addCaretListener(new CaretListener() {
65 @Override
66 public void caretUpdate(CaretEvent e) {
67 String str = sendArea.getText();
68 if (str.length() > 5000) {
69 ChatRoomUtil.showErrorBox("字数过多,超出限制。");
70 }
71 }
72 });
73 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
74 this.addWindowListener(new WindowAdapter() {
75 public void windowClosing(WindowEvent e) {//关闭窗口后,ChatRoom要移除该对话
76 chatRoom.removeDialog(otsId);
77 dispose();
78 }
79 });
80 new java.util.Timer().schedule(new TimerTask() {
81 public void run() {
82 repaint();
83 }
84 }, 400, 400);
85 }
86 public int addRecord(String mesg) {
87 chatArea.append(mesg + "\n");
88 chatArea.setCaretPosition(chatArea.getText().length());
89 this.validate();
90 return 0;
91 }
92 private String sendMessage(String mesg) {
93 Send sendClient = new Send();
94 sendClient.connect(serverIP, serverPort, 1000);
95 String getm = sendClient.send(
96 "chat" + otsId + ":" + myId + ":" + myId + ": \n" + mesg);
97 addRecord(myId + ": \n" + mesg);
98 return getm;
99 }
100 @Override
101 public void actionPerformed(ActionEvent e) {
102 if (e.getSource().getClass() == JButton.class) {
103 sendMessage(sendArea.getText());
104 sendArea.setText("");
105 }
106 }
107 }
Users.txt
1 1:1
2 2:2
3 3:3
4 4:4
5 5:5
6 6:6
7 7:7
8 8:8
9 9:9
10 10:10
11 11:11
12 12:12
13 13:13
14 14:14
15 15:15
16 16:16
17 17:17
18 18:18
19 19:19
20 20:20
21 21:21
22 22:22
23 23:23
24 24:24
25 25:25
26 26:26
27 27:27
28 28:28
29 29:29
30 30:30
31 31:31
32 32:32
33 33:33
34 34:34
35 35:35
36 36:36
37 37:37
38 38:38
39 39:39
40 40:40
41 41:41
42 42:42
43 43:43
44 44:44
45 45:45
46 46:46
47 47:47
48 48:48
49 49:49
50 50:50
51 51:51
52 52:52
53 53:53
54 54:54
55 55:55
56 56:56
57 57:57
58 58:58
59 59:59
60 60:60
61 61:61
62 62:62
63 63:63
64 64:64
65 65:65
66 66:66
67 67:67
68 68:68
69 69:69
70 70:70
71 71:71
72 72:72
73 73:73
74 74:74
75 75:75
76 76:76
77 77:77
78 78:78
79 79:79
80 80:80
81 81:81
82 82:82
83 83:83
84 84:84
85 85:85
86 86:86
87 87:87
88 88:88
89 89:89
90 90:90
91 91:91
92 92:92
93 93:93
94 94:94
95 95:95
96 96:96
97 aa:aa
98 qq:qq
99 ww:ww
100 ee:ee
101 guochengxin:guochengxin
102 huoda:huoda
103 zhangfa:zhangfa
104 hanyu:hanyu
105 maxuewei:maxuewei
106 lizeyu:lizeyu
End
写于大三下实训期间
随笔写于2016.7.13