功能:
登录
若用户账号不存在,弹出错误
若用户密码错误,弹出错误
若用户账号已在线,弹出错误
注册
若用户已注册,弹出错误
聊天室
多人聊天,类似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