1 packagecom.company;2
3 importjava.awt.BorderLayout;4 importjava.awt.Color;5 importjava.awt.Font;6 importjava.awt.GridLayout;7 importjava.awt.Toolkit;8 importjava.awt.event.ActionEvent;9 importjava.awt.event.ActionListener;10 importjava.awt.event.WindowAdapter;11 importjava.awt.event.WindowEvent;12 import java.io.*;13 importjava.net.BindException;14 importjava.net.InetAddress;15 importjava.net.ServerSocket;16 importjava.net.Socket;17 importjava.sql.Connection;18 importjava.sql.DriverManager;19 importjava.sql.ResultSet;20 importjava.sql.Statement;21 importjava.util.ArrayList;22 importjava.util.HashMap;23 importjava.util.Map;24 importjava.util.StringTokenizer;25
26 import javax.swing.*;27 importjavax.swing.border.TitledBorder;28 importjavax.swing.event.ListSelectionEvent;29 importjavax.swing.event.ListSelectionListener;30
31 //import socket_chat_server.Server.ClientThread;32 //import socket_chat_server.Server.SelecTry;
33
34 public classClient{35
36 privateJPanel sendPanel;37 privateJButton btn_send_file;38 privateJFrame frame;39 privateJList userList;40 privateJTextArea textArea;41 privateJTextField textField;42 privateJTextField txt_port;43 privateJTextField txt_hostIp;44 privateJTextField txt_name;45 privateJButton btn_start;46 privateJButton btn_stop;47 privateJButton btn_send;48 privateJPanel northPanel;49 privateJPanel southPanel;50 privateJScrollPane rightScroll;51 privateJScrollPane leftScroll;52 privateJSplitPane centerSplit;53
54 privateJPanel logPanle;55 privateJFrame loginframe;56 privateJLabel label_username;57 privateJLabel label_password;58 privateJTextField txt_login_name;59 privateJTextField txt_password;60 privateJTextField txt_login_ip;61 privateJTextField txt_login_port;62 privateJTextField txt_login_forget;63 privateJButton btn_submit;64 privateJButton btn_zhuce;65 privateJButton btn_forget_pass;66
67 privateDefaultListModel listModel;68 private boolean isConnected = false;69
70 private intsendfor_who;71 private int server_port=0;72
73 privateServerSocket serverSocket;74 privateServerThread serverThread;75 privateSocket socketfor_p2p;76 private boolean isConnected_p2p = false;77 private ArrayList clients;//客户线程数组
78 private PrintWriter P2P_printWriter;//点对点服务的输出流
79 private BufferedReader P2P_bufferReader;//点对点服务的输入流
80 private MessageThread_P2P messageThread_for_p2p;//负责接收p2p消息的线程
81 private Map P2P_connected_user = new HashMap();82
83 privateSocket socket;84 privatePrintWriter writer;85 privateBufferedReader reader;86 private MessageThread messageThread;//负责接收消息的线程
87 private Map onLineUsers = new HashMap();//所有在线用户
88 private String myIP = "";//每一个客户端都有唯一的IP地址89
90 //主方法,程序入口
91 public static void main(String[] args) throwsBindException {92 newClient();93
94 }95
96 class SelecTry implementsListSelectionListener97 {98 int change=0,who;99 public voidvalueChanged(ListSelectionEvent e){100 //System.out.println("you selected:"+listModel.getElementAt(userList.getSelectedIndex()));
101 sendfor_who=userList.getSelectedIndex();102 isConnected_p2p = false;103 }104
105 }106
107 /**
108 * 连接服务器109 *110 *@paramport111 *@paramhostIp112 *@paramname113 */
114 public boolean connectServer_p2p(intport, String hostIp, String name) {115 //连接服务器
116 try{117 socketfor_p2p = new Socket(hostIp, port);//根据端口号和服务器ip建立连接
118 P2P_printWriter = newPrintWriter(socketfor_p2p.getOutputStream());119 P2P_bufferReader = new BufferedReader(newInputStreamReader(socketfor_p2p120 .getInputStream()));121
122 messageThread_for_p2p = newMessageThread_P2P(P2P_bufferReader);123 messageThread_for_p2p.start();124 P2P_connected_user.put(name,true);125 isConnected_p2p = true;//已经连接上了
126 return true;127 } catch(Exception e) {128 textArea.append("与端口号为:" + port + " IP地址为:" +hostIp129 + " 的服务连接失败!" + "\r\n");130 isConnected_p2p = false;//未连接上
131 return false;132 }133 }134
135 /**
136 * 关闭服务137 */
138 @SuppressWarnings("deprecation")139 public voidcloseServer() {140 try{141 if (serverThread != null)142 serverThread.stop();//停止服务器线程
143
144 for (int i = clients.size() - 1; i >= 0; i--) {145 //给所有在线用户发送关闭命令
146 clients.get(i).getWriter().println("CLOSE#"+frame.getTitle());147 clients.get(i).getWriter().flush();148 //释放资源
149 clients.get(i).stop();//停止此条为客户端服务的线程
150 clients.get(i).reader_ptp.close();151 clients.get(i).writer_ptp.close();152 clients.get(i).socket.close();153 clients.remove(i);154 }155 if (serverSocket != null) {156 serverSocket.close();//关闭服务器端连接
157 }158 listModel.removeAllElements();//清空用户列表159 //isStart = false;
160 } catch(IOException e) {161 e.printStackTrace();162 //isStart = true;
163 }164 }165
166 //不断接收消息的线程
167 class MessageThread_P2P extendsThread {168 privateBufferedReader reader_ptp;169
170 //接收消息线程的构造方法
171 publicMessageThread_P2P(BufferedReader reader) {172 this.reader_ptp =reader;173
174 }175
176 //被动的关闭连接
177 public synchronized void closeCon() throwsException {178 System.out.println("close :*************");179 //被动的关闭连接释放资源
180 if (reader_ptp != null) {181 reader_ptp.close();182 }183 if (P2P_printWriter != null) {184 P2P_printWriter.close();185 }186 if (socketfor_p2p != null) {187 socketfor_p2p.close();188 }189 isConnected_p2p = false;//修改状态为断开
190
191 }192
193 public voidrun() {194 String message = "";195 while (true) {196 try{197 message =reader_ptp.readLine();198 StringTokenizer stringTokenizer = newStringTokenizer(199 message, "/#");200 String command = stringTokenizer.nextToken();//命令
201 if (command.equals("CLOSE"))//服务器已关闭命令
202 {203 String user =stringTokenizer.nextToken();204 textArea.append("用户 "+user+" 已下线,p2p服务已关闭!\r\n");205 closeCon();//被动的关闭连接
206 JOptionPane.showMessageDialog(frame, "用户 "+user+" 已下线,p2p服务已关闭!", "错误",207 JOptionPane.ERROR_MESSAGE);208 return;//结束线程
209 } else if (command.equals("FILE")) {210 int portNumber =Integer.parseInt(stringTokenizer.nextToken());211 String fileName =stringTokenizer.nextToken();212 long fileSize =Long.parseLong(stringTokenizer.nextToken());213 String ip =stringTokenizer.nextToken();214 String Nickname =stringTokenizer.nextToken();215 ReceiveFileThread receiveFile = newReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname);216 receiveFile.start();217 textArea.append("从 "+Nickname+" 接受文件:"+fileName+",大小为:"+fileSize218 +"ip:"+ip+"port:"+portNumber+"\r\n");219 } else {//普通消息
220 textArea.append(""+message + "\r\n");221 }222 } catch(IOException e) {223 e.printStackTrace();224 } catch(Exception e) {225 e.printStackTrace();226 }227 }228 }229 }230
231 /**
232 * 启动服务器233 *234 *@paramport235 *@throwsjava.net.BindException236 */
237 public void serverStart(int port) throwsjava.net.BindException {238 try{239 clients = new ArrayList();240 serverSocket = newServerSocket(port);241 serverThread = newServerThread(serverSocket);242 serverThread.start();243 server_port =serverSocket.getLocalPort();244 InetAddress addr =InetAddress.getLocalHost();245 myIP = addr.getHostAddress();//获得本机IP246 //myIP = serverSocket.getInetAddress().getHostAddress();
247 System.out.println("mmyIP=="+myIP+"\r\n");248 } catch(BindException e) {249 throw new BindException("端口号已被占用,请换一个!");250 } catch(Exception e1) {251 e1.printStackTrace();252 throw new BindException("启动服务器异常!");253 }254 }255
256 /**
257 * 为另一个主动链接的客户端提供服务的线程258 */
259 class ClientThread extendsThread {260 privateSocket socket;261 privateBufferedReader reader_ptp;262 privatePrintWriter writer_ptp;263 privateUser user;264
265 publicBufferedReader getReader() {266 returnreader_ptp;267 }268
269 publicPrintWriter getWriter() {270 returnwriter_ptp;271 }272
273 publicUser getUser() {274 returnuser;275 }276
277 //客户端线程的构造方法
278 publicClientThread(Socket socket) {279 try{280 this.socket =socket;281 reader_ptp = new BufferedReader(newInputStreamReader(socket282 .getInputStream()));283 writer_ptp = newPrintWriter(socket.getOutputStream());284
285 //接收客户端的基本用户信息
286 String inf =reader_ptp.readLine();287 StringTokenizer st = new StringTokenizer(inf, "#");288 user = newUser(st.nextToken(), socket.getLocalAddress().toString());289 //反馈连接成功信息
290 writer_ptp.println(frame.getTitle()+" 对你说: "+user.getName()+"/"+user.getIp()+"你好!"+"与我"+frame.getTitle()+"建立链接成功!");291 writer_ptp.flush();292 // //反馈当前在线用户信息293 //if (clients.size() > 0) {294 //String temp = "";295 //for (int i = clients.size() - 1; i >= 0; i--) {296 //temp += (clients.get(i).getUser().getName() + "/" + clients297 //.get(i).getUser().getIp())298 //+ "#";299 //}300 //writer.println("USERLIST#" + clients.size() + "#" + temp);301 //writer.flush();302 //}303 // //向所有在线用户发送该用户上线命令304 //for (int i = clients.size() - 1; i >= 0; i--) {305 //clients.get(i).getWriter().println(306 //"ADD#" + user.getName() + user.getIp());307 //clients.get(i).getWriter().flush();308 //}
309 } catch(IOException e) {310 e.printStackTrace();311 }312 }313
314 @SuppressWarnings("deprecation")315 public void run() {//不断接收客户端的消息,进行处理。
316 String message = null;317 while (true) {318 try{319 message = reader_ptp.readLine();//接收客户端消息
320 StringTokenizer stringTokenizer = new StringTokenizer(message,"/#");321 String command =stringTokenizer.nextToken();322 if (command.equals("CLOSE"))//下线命令
323 {324 textArea.append("与"+this.getUser().getName()325 + this.getUser().getIp() + "建立连接成功!\r\n");326 //断开连接释放资源
327 this.getUser().setState(0);328 reader.close();329 writer.close();330 socket.close();331
332 } else if (command.equals("FILE")) {333 int portNumber =Integer.parseInt(stringTokenizer.nextToken());334 String fileName =stringTokenizer.nextToken();335 long fileSize =Long.parseLong(stringTokenizer.nextToken());336 String ip =stringTokenizer.nextToken();337 String Nickname =stringTokenizer.nextToken();338 ReceiveFileThread receiveFile = newReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname);339 receiveFile.start();340 textArea.append("从 "+Nickname+" 接受文件 :"+fileName+",大小为: "+fileSize341 +" ip: "+ip+" port:"+portNumber+"\r\n");342 }else{343 textArea.append(user.getName()+" 对你说: "+message+"\r\n");344 }345 } catch(IOException e) {346 e.printStackTrace();347 }348 }349 }350
351 }352
353 /**
354 * 服务线程355 */
356 class ServerThread extendsThread {357 privateServerSocket serverSocket;358
359 //服务器线程的构造方法
360 publicServerThread(ServerSocket serverSocket) {361 this.serverSocket =serverSocket;362 }363
364 public voidrun() {365 while (true) {//不停的等待客户端的链接
366 try{367 Socket socket =serverSocket.accept();368 ClientThread client = newClientThread(socket);369 client.start();//开启对此客户端服务的线程
370 clients.add(client);371 textArea.append("有新用户p2p链接\r\n");372 //user_name_update();
373 } catch(IOException e) {374 e.printStackTrace();375 }376 }377 }378 }379
380
381 public voidsendFile() {382 //文件选择对话框启动,当选择了文件以后给每一个client发送文件
383 JFileChooser sourceFileChooser = new JFileChooser(".");384 sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);385 int status =sourceFileChooser.showOpenDialog(frame);386 File sourceFile = newFile(sourceFileChooser.getSelectedFile().getPath());387 //服务器text area提示
388 textArea.append("发送文件:" + sourceFile.getName() + "\r\n");389
390 if(sendfor_who==0){391 textArea.append("对服务器发送文件!");392 }else{393 StringTokenizer st = new StringTokenizer(listModel.getElementAt(sendfor_who)+"", "---()");394 String user_name =st.nextToken();395 String user_state =st.nextToken();396 if (user_state.equals("在线")) {397 for (int i = clients.size()-1; i >= 0; i--) {398 if(clients.get(i).getUser().getName().equals(user_name)) {399 SendFileThread sendFile = newSendFileThread(frame, clients.get(i).socket, frame.getTitle(), sourceFileChooser, status);400 sendFile.start();401 //client端提示
402 textArea.append("给 "+user_name+" 发送一个文件:" + sourceFile.getName() + "\r\n");403 return;404 }405 }406 SendFileThread sendFile = newSendFileThread(frame, socketfor_p2p, frame.getTitle(), sourceFileChooser, status);407 sendFile.start();408 //client端提示
409 textArea.append("给 "+user_name+" 发送一个文件:" + sourceFile.getName() + "\r\n");410 }else{411 JOptionPane.showMessageDialog(frame, "用户不在线,不能发送文件!");412 }413 }414
415 }416
417
418
419 //执行发送
420 public voidsend() {421 if (!isConnected) {422 JOptionPane.showMessageDialog(frame, "还没有连接服务器,无法发送消息!", "错误",423 JOptionPane.ERROR_MESSAGE);424 return;425 }426 String message =textField.getText().trim();427 if (message == null || message.equals("")) {428 JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误",429 JOptionPane.ERROR_MESSAGE);430 return;431 }432 //sendMessage(frame.getTitle() + "#" + "ALL" + "#" + message);
433 if(sendfor_who==0){434 sendMessage(frame.getTitle() + "#" + "ALL" + "#" +message);435 textField.setText(null);436 }else{437 StringTokenizer st = new StringTokenizer(listModel.getElementAt(sendfor_who)+"", "---()");438 String user_name =st.nextToken();439 String user_state =st.nextToken();440 if (user_state.equals("在线")) {441 for (int i = clients.size()-1; i >= 0; i--) {442 if(clients.get(i).getUser().getName().equals(user_name)) {443 clients.get(i).writer_ptp.println("对 "+user_name+" 说: "+message+"\r\n");444 clients.get(i).writer_ptp.flush();445 textArea.append("对 "+user_name+" 说: "+message+"\r\n");446 textField.setText(null);447 return;448 }449 }450 if (!isConnected_p2p) {451 JOptionPane.showMessageDialog(frame, "点对点即将连接!");452 sendMessage("P2P#"+user_name);453 }else{454 P2P_printWriter.println(message);455 P2P_printWriter.flush();456 textArea.append("对 "+user_name+" 说: "+message+"\r\n");457 textField.setText(null);458 }459
460 }else{461 JOptionPane.showMessageDialog(frame, "用户不在线,已存为留言!");462 sendMessage("LIXIAN#"+frame.getTitle() + "#" + user_name + "#" +message);463 textArea.append("对 "+user_name+" 留言: "+message+"\r\n");464 textField.setText(null);465 }466 }467 }468
469 public voidLogin(){470 Font font = new Font("宋体", 1, 16);471
472 logPanle = newJPanel();473 //logPanle.setLayout(new GridLayout(2, 2));
474 logPanle.setBounds(2, 45, 250, 225);475 logPanle.setBackground(Color.lightGray);476 logPanle.setLayout(new GridLayout(5, 2, 20, 20));477
478 label_username = new JLabel("用户名:");479 label_username.setFont(font);480 label_username.setHorizontalAlignment(SwingConstants.CENTER);481 logPanle.add(label_username);482
483 txt_login_name = new JTextField("name");484 txt_login_name.setFont(font);485 logPanle.add(txt_login_name);486
487 label_password = new JLabel("密 码:");488 label_password.setFont(font);489 label_password.setHorizontalAlignment(SwingConstants.CENTER);490 logPanle.add(label_password);491
492 txt_password = new JTextField("");493 txt_password.setFont(font);494 logPanle.add(txt_password);495
496 txt_login_ip = new JTextField("127.0.0.1");497 txt_login_ip.setFont(font);498 logPanle.add(txt_login_ip);499
500 txt_login_port = new JTextField("6666");501 txt_login_port.setFont(font);502 logPanle.add(txt_login_port);503
504 logPanle.add(txt_login_ip);505 logPanle.add(txt_login_port);506
507 btn_submit = new JButton("登陆");508 btn_submit.setFont(font);509 btn_submit.addActionListener(newActionListener() {510 public voidactionPerformed(ActionEvent e) {511 intport;512 String message_name =txt_login_name.getText().trim();513 if (message_name == null || message_name.equals("")) {514 JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",515 JOptionPane.ERROR_MESSAGE);516 return;517 }518 String message_pw =txt_password.getText().trim();519 if (message_pw == null || message_pw.equals("")) {520 JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误",521 JOptionPane.ERROR_MESSAGE);522 return;523 }524 if(isConnected) {525 String message1 =txt_login_name.getText().trim();526 if (message1 == null || message1.equals("")) {527 JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",528 JOptionPane.ERROR_MESSAGE);529 return;530 }531 String message2 =txt_password.getText().trim();532 if (message2 == null || message2.equals("")) {533 JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误",534 JOptionPane.ERROR_MESSAGE);535 return;536 }537 sendMessage("USERLOGIN#"+message1+"#"+message2+"#"+server_port+"#"+myIP);538 return;539 }else{540 try{541 try{542 port =Integer.parseInt(txt_login_port.getText().trim());543 } catch(NumberFormatException e2) {544 throw new Exception("端口号不符合要求!端口为整数!");545 }546 String hostIp =txt_login_ip.getText().trim();547 String name =txt_login_name.getText().trim();548 if (name.equals("") || hostIp.equals("")) {549 throw new Exception("姓名、服务器IP不能为空!");550 }551 boolean flag =connectServer(port, hostIp, name);552 if (flag == false) {553 throw new Exception("与服务器连接失败!");554 }555 frame.setTitle(name);556 listModel.addElement("全部用户");557 } catch(Exception exc) {558 JOptionPane.showMessageDialog(loginframe, exc.getMessage(),559 "错误", JOptionPane.ERROR_MESSAGE);560 return;561 }562 }563
564 sendMessage("USERLOGIN#"+message_name+"#"+message_pw+"#"+server_port+"#"+myIP);565 }566 });567 logPanle.add(btn_submit);568
569 btn_zhuce = new JButton("注册");570 btn_zhuce.setFont(font);571 btn_zhuce.addActionListener(newActionListener() {572 public voidactionPerformed(ActionEvent e) {573 intport;574 String message_name =txt_login_name.getText().trim();575 if (message_name == null || message_name.equals("")) {576 JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",577 JOptionPane.ERROR_MESSAGE);578 return;579 }580 String message_pw =txt_password.getText().trim();581 if (message_pw == null || message_pw.equals("")) {582 JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误",583 JOptionPane.ERROR_MESSAGE);584 return;585 }586 String message_yx =txt_login_forget.getText().trim();587 if (message_yx == null || message_yx.equals("")) {588 JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误",589 JOptionPane.ERROR_MESSAGE);590 return;591 }592
593 if(isConnected) {594 String message1 =txt_login_name.getText().trim();595 if (message1 == null || message1.equals("")) {596 JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",597 JOptionPane.ERROR_MESSAGE);598 return;599 }600 String message2 =txt_password.getText().trim();601 if (message2 == null || message2.equals("")) {602 JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误",603 JOptionPane.ERROR_MESSAGE);604 return;605 }606 String message3 =txt_login_forget.getText().trim();607 if (message3 == null || message3.equals("")) {608 JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误",609 JOptionPane.ERROR_MESSAGE);610 return;611 }612 sendMessage("USERZHUCE#"+message1+"#"+message2+"#"+message3);613 return;614 }else{615 try{616 try{617 port =Integer.parseInt(txt_login_port.getText().trim());618 } catch(NumberFormatException e2) {619 throw new Exception("端口号不符合要求!端口为整数!");620 }621 String hostIp =txt_login_ip.getText().trim();622 String name =txt_login_name.getText().trim();623 if (name.equals("") || hostIp.equals("")) {624 throw new Exception("姓名、服务器IP不能为空!");625 }626 boolean flag =connectServer(port, hostIp, name);627 if (flag == false) {628 throw new Exception("与服务器连接失败!");629 }630 frame.setTitle(name);631 listModel.addElement("全部用户");632 } catch(Exception exc) {633 JOptionPane.showMessageDialog(frame, exc.getMessage(),634 "错误", JOptionPane.ERROR_MESSAGE);635 return;636 }637 }638
639
640 sendMessage("USERZHUCE#"+message_name+"#"+message_pw+"#"+message_yx);641 }642 });643 logPanle.add(btn_zhuce);644
645
646
647 txt_login_forget = new JTextField("");648 txt_login_forget.setFont(font);649 logPanle.add(txt_login_forget);650
651 btn_forget_pass = new JButton("密码找回");652 btn_forget_pass.setFont(font);653 btn_forget_pass.addActionListener(newActionListener() {654 public voidactionPerformed(ActionEvent e) {655 intport;656
657 String message_name =txt_login_name.getText().trim();658 if (message_name == null || message_name.equals("")) {659 JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",660 JOptionPane.ERROR_MESSAGE);661 return;662 }663 String message_yx =txt_login_forget.getText().trim();664 if (message_yx == null || message_yx.equals("")) {665 JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误",666 JOptionPane.ERROR_MESSAGE);667 return;668 }669 String message_pw =txt_password.getText().trim();670 if (message_pw == null || message_pw.equals("")) {671 JOptionPane.showMessageDialog(logPanle, "修改密码不能为空!", "错误",672 JOptionPane.ERROR_MESSAGE);673 return;674 }675
676 if(isConnected) {677 String message1 =txt_login_name.getText().trim();678 if (message1 == null || message1.equals("")) {679 JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",680 JOptionPane.ERROR_MESSAGE);681 return;682 }683 String message2 =txt_login_forget.getText().trim();684 if (message2 == null || message2.equals("")) {685 JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误",686 JOptionPane.ERROR_MESSAGE);687 return;688 }689 String message3 =txt_password.getText().trim();690 if (message3 == null || message3.equals("")) {691 JOptionPane.showMessageDialog(logPanle, "修改密码不能为空!", "错误",692 JOptionPane.ERROR_MESSAGE);693 return;694 }695 sendMessage("USERFORGET#"+message1+"#"+message2+"#"+message3);696 return;697 }else{698 try{699 try{700 port =Integer.parseInt(txt_login_port.getText().trim());701 } catch(NumberFormatException e2) {702 throw new Exception("端口号不符合要求!端口为整数!");703 }704 String hostIp =txt_login_ip.getText().trim();705 String name =txt_login_name.getText().trim();706 if (name.equals("") || hostIp.equals("")) {707 throw new Exception("姓名、服务器IP不能为空!");708 }709 boolean flag =connectServer(port, hostIp, name);710 if (flag == false) {711 throw new Exception("与服务器连接失败!");712 }713 frame.setTitle(name);714 listModel.addElement("全部用户");715 } catch(Exception exc) {716 JOptionPane.showMessageDialog(frame, exc.getMessage(),717 "错误", JOptionPane.ERROR_MESSAGE);718 return;719 }720 }721
722 sendMessage("USERFORGET#"+message_name+"#"+message_yx+"#"+message_pw);723 }724 });725 logPanle.add(btn_forget_pass);726
727
728 logPanle.setBorder(new TitledBorder("登陆"));729 loginframe = new JFrame("登陆窗口");730 loginframe.add(logPanle,"Center");731 loginframe.setSize(300, 300);732 int screen_width =Toolkit.getDefaultToolkit().getScreenSize().width;733 int screen_height =Toolkit.getDefaultToolkit().getScreenSize().height;734 loginframe.setLocation((screen_width - loginframe.getWidth()) / 2,735 (screen_height - loginframe.getHeight()) / 2);736 loginframe.setVisible(true);737
738 //关闭窗口时事件
739 loginframe.addWindowListener(newWindowAdapter() {740 public voidwindowClosing(WindowEvent e) {741 if(isConnected) {742 closeConnection();//关闭连接
743 closeServer();//关闭服务程序
744 }745 System.exit(0);//退出程序
746 }747 });748 }749
750 //构造方法
751 public Client() throwsBindException {752
753 serverStart(0);754
755 SelecTry selectIndex=newSelecTry();756
757 textArea = newJTextArea();758 textArea.setEditable(false);759 textArea.setForeground(Color.blue);760 textField = newJTextField();761 txt_port = new JTextField("6666");762 txt_hostIp = new JTextField("127.0.0.1");763 txt_name = new JTextField("姓名");764 btn_start = new JButton("连接");765 btn_stop = new JButton("断开");766 btn_send = new JButton("发送");767 btn_send_file = new JButton("文件");768 listModel = newDefaultListModel();769 userList = newJList(listModel);770 //listModel.addElement("全部用户");
771 userList.addListSelectionListener(selectIndex);772 northPanel = newJPanel();773 northPanel.setLayout(new GridLayout(1, 7));774 northPanel.add(new JLabel(" 端口"));775 northPanel.add(txt_port);776 northPanel.add(new JLabel(" 服务器IP"));777 northPanel.add(txt_hostIp);778 northPanel.add(new JLabel(" 姓名"));779 northPanel.add(txt_name);780 northPanel.add(btn_start);781 northPanel.add(btn_stop);782 northPanel.setBorder(new TitledBorder("连接信息"));783
784 rightScroll = newJScrollPane(textArea);785 rightScroll.setBorder(new TitledBorder("消息显示区"));786 leftScroll = newJScrollPane(userList);787 leftScroll.setBorder(new TitledBorder("用户列表"));788 southPanel = new JPanel(newBorderLayout());789 sendPanel = new JPanel(newBorderLayout());790 southPanel.setBorder(new TitledBorder("写消息"));791 southPanel.add(textField, "Center");792 sendPanel.add(btn_send, BorderLayout.NORTH);793 sendPanel.add(btn_send_file, BorderLayout.SOUTH);794 southPanel.add(sendPanel, "East");795
796
797 centerSplit = newJSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScroll,798 rightScroll);799 centerSplit.setDividerLocation(150);800
801 frame = new JFrame("客户机");802 //更改JFrame的图标:803 //frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.getResource("qq.png")));
804 frame.setLayout(newBorderLayout());805 frame.add(northPanel, "North");806 frame.add(centerSplit, "Center");807 frame.add(southPanel, "South");808 frame.setSize(600, 400);809 int screen_width =Toolkit.getDefaultToolkit().getScreenSize().width;810 int screen_height =Toolkit.getDefaultToolkit().getScreenSize().height;811 frame.setLocation((screen_width - frame.getWidth()) / 2,812 (screen_height - frame.getHeight()) / 2);813 frame.setVisible(false);814
815 //写消息的文本框中按回车键时事件
816 textField.addActionListener(newActionListener() {817 public voidactionPerformed(ActionEvent arg0) {818 send();819 }820 });821
822 //单击发送按钮时事件
823 btn_send.addActionListener(newActionListener() {824 public voidactionPerformed(ActionEvent e) {825 send();826 }827 });828
829 //单机文件按钮时事件
830 btn_send_file.addActionListener(newActionListener() {831 public voidactionPerformed(ActionEvent arg0) {832 sendFile();833 }834 });835
836 //单击连接按钮时事件837 //btn_start.addActionListener(new ActionListener() {838 //public void actionPerformed(ActionEvent e) {839 //int port;840 //if (isConnected) {841 //JOptionPane.showMessageDialog(frame, "已处于连接上状态,不要重复连接!",842 //"错误", JOptionPane.ERROR_MESSAGE);843 //return;844 //}845 //try {846 //try {847 //port = Integer.parseInt(txt_port.getText().trim());848 //} catch (NumberFormatException e2) {849 //throw new Exception("端口号不符合要求!端口为整数!");850 //}851 //String hostIp = txt_hostIp.getText().trim();852 //String name = txt_name.getText().trim();853 //if (name.equals("") || hostIp.equals("")) {854 //throw new Exception("姓名、服务器IP不能为空!");855 //}856 //boolean flag = connectServer(port, hostIp, name);857 //if (flag == false) {858 //throw new Exception("与服务器连接失败!");859 //}860 //listModel.addElement("全部用户");861 //frame.setTitle(name);862 //JOptionPane.showMessageDialog(frame, "成功连接!");863 //} catch (Exception exc) {864 //JOptionPane.showMessageDialog(frame, exc.getMessage(),865 //"错误", JOptionPane.ERROR_MESSAGE);866 //}867 //}868 //});869
870 //单击断开按钮时事件
871 btn_stop.addActionListener(newActionListener() {872 public voidactionPerformed(ActionEvent e) {873 if (!isConnected) {874 JOptionPane.showMessageDialog(frame, "已处于断开状态,不要重复断开!",875 "错误", JOptionPane.ERROR_MESSAGE);876 return;877 }878 try{879 boolean flag = closeConnection();//断开连接
880 closeServer();881 if (flag == false) {882 throw new Exception("断开连接发生异常!");883 }884 JOptionPane.showMessageDialog(frame, "成功断开!");885 frame.setVisible(false);886 textArea.setText("");887 loginframe.setVisible(true);888 listModel.removeAllElements();889 } catch(Exception exc) {890 JOptionPane.showMessageDialog(frame, exc.getMessage(),891 "错误", JOptionPane.ERROR_MESSAGE);892 }893 }894 });895
896 //关闭窗口时事件
897 frame.addWindowListener(newWindowAdapter() {898 public voidwindowClosing(WindowEvent e) {899 if(isConnected) {900 closeConnection();//关闭连接
901 closeServer();//关闭服务程序
902 }903 System.exit(0);//退出程序
904 }905 });906 Login();907 }908
909 /**
910 * 连接服务器911 *912 *@paramport913 *@paramhostIp914 *@paramname915 */
916 public boolean connectServer(intport, String hostIp, String name) {917 //连接服务器
918 try{919 socket = new Socket(hostIp, port);//根据端口号和服务器ip建立连接
920 writer = newPrintWriter(socket.getOutputStream());921 reader = new BufferedReader(newInputStreamReader(socket922 .getInputStream()));923 //发送客户端用户基本信息(用户名和ip地址)
924 sendMessage(name + "#" +socket.getLocalAddress().toString());925 //开启接收消息的线程
926 messageThread = newMessageThread(reader, textArea);927 messageThread.start();928 isConnected = true;//已经连接上了
929 return true;930 } catch(Exception e) {931 textArea.append("与端口号为:" + port + " IP地址为:" +hostIp932 + " 的服务器连接失败!" + "\r\n");933 isConnected = false;//未连接上
934 return false;935 }936 }937
938 /**
939 * 发送消息940 *941 * #param message942 */
943 public voidsendMessage(String message) {944 writer.println(message);945 writer.flush();946 }947
948 /**
949 * 客户端主动关闭连接950 */
951 @SuppressWarnings("deprecation")952 public synchronized booleancloseConnection() {953 try{954 sendMessage("CLOSE");//发送断开连接命令给服务器
955 messageThread.stop();//停止接受消息线程956 //释放资源
957 if (reader != null) {958 reader.close();959 }960 if (writer != null) {961 writer.close();962 }963 if (socket != null) {964 socket.close();965 }966 isConnected = false;967 listModel.removeAllElements();968 return true;969 } catch(IOException e1) {970 e1.printStackTrace();971 isConnected = true;972 return false;973 }974 }975
976 //不断接收消息的线程
977 class MessageThread extendsThread {978 privateBufferedReader reader;979 privateJTextArea textArea;980
981 //接收消息线程的构造方法
982 publicMessageThread(BufferedReader reader, JTextArea textArea) {983 this.reader =reader;984 this.textArea =textArea;985 }986
987 //被动的关闭连接
988 public synchronized void closeCon() throwsException {989 //清空用户列表
990 listModel.removeAllElements();991 //被动的关闭连接释放资源
992 if (reader != null) {993 reader.close();994 }995 if (writer != null) {996 writer.close();997 }998 if (socket != null) {999 socket.close();1000 }1001 isConnected = false;//修改状态为断开
1002
1003 }1004
1005 public voidrun() {1006 String message = "";1007 while (true) {1008 try{1009 message =reader.readLine();1010 StringTokenizer stringTokenizer = newStringTokenizer(1011 message, "/#");1012 String command = stringTokenizer.nextToken();//命令
1013 if (command.equals("CLOSE"))//服务器已关闭命令
1014 {1015 textArea.append("服务器已关闭!\r\n");1016 closeCon();//被动的关闭连接
1017 JOptionPane.showMessageDialog(frame, "服务器已关闭!", "错误",1018 JOptionPane.ERROR_MESSAGE);1019 frame.setVisible(false);1020 textArea.setText("");1021 loginframe.setVisible(true);1022 return;//结束线程
1023 } else if (command.equals("ADD")) {//有用户上线更新在线列表
1024 String username = "";1025 String userIp = "";1026 if ((username = stringTokenizer.nextToken()) != null
1027 && (userIp = stringTokenizer.nextToken()) != null) {1028 User user = newUser(username, userIp);1029 onLineUsers.put(username, user);1030 listModel.addElement(username);1031 }1032 } else if (command.equals("DELETE")) {//有用户下线更新在线列表
1033 String username =stringTokenizer.nextToken();1034 User user =(User) onLineUsers.get(username);1035 onLineUsers.remove(user);1036 listModel.removeElement(username);1037 } else if (command.equals("USERLIST")) {//加载在线用户列表
1038 listModel.removeAllElements();1039 listModel.addElement("全部用户");1040 StringTokenizer strToken ;1041 String user ;//命令
1042 int size =Integer1043 .parseInt(stringTokenizer.nextToken());1044 String username = null;1045 String userIp = null;1046 for (int i = 0; i < size-1; i++) {1047 username =stringTokenizer.nextToken();1048 strToken = new StringTokenizer(username, "---()");1049 if(strToken.nextToken().equals(frame.getTitle())) {1050 continue;1051 }else{1052 listModel.addElement(username);1053 }1054 //userIp = stringTokenizer.nextToken();1055 //User user = new User(username, userIp);1056 //onLineUsers.put(username, user);
1057 }1058 } else if (command.equals("MAX")) {//人数已达上限
1059 textArea.append(stringTokenizer.nextToken()1060 + stringTokenizer.nextToken() + "\r\n");1061 closeCon();//被动的关闭连接
1062 JOptionPane.showMessageDialog(frame, "服务器缓冲区已满!", "错误",1063 JOptionPane.ERROR_MESSAGE);1064 return;//结束线程
1065 } else if(command.equals("FILE")){1066 int portNumber =Integer.parseInt(stringTokenizer.nextToken());1067 String fileName =stringTokenizer.nextToken();1068 long fileSize =Long.parseLong(stringTokenizer.nextToken());1069 String ip =stringTokenizer.nextToken();1070 String Nickname =stringTokenizer.nextToken();1071 ReceiveFileThread receiveFile = newReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname);1072 receiveFile.start();1073 textArea.append("从"+Nickname+"接受文件:"+fileName+",大小为:"+fileSize1074 +"ip:"+ip+"port:"+portNumber+"\r\n");1075 }else if(command.equals("USERLOGIN")){1076 String st =stringTokenizer.nextToken();1077 if(st.equals("OK")){1078 JOptionPane.showMessageDialog(loginframe, "登陆成功!");1079 loginframe.setVisible(false);1080 txt_name.setText(txt_login_name.getText());1081 frame.setVisible(true);1082 int count =stringTokenizer.countTokens();1083 while(true){1084 if(count==0){1085 break;1086 }1087 textArea.append(stringTokenizer.nextToken()+" 对你留言 ,");1088 textArea.append("时间: "+stringTokenizer.nextToken()+"\r\n ");1089 textArea.append("留言内容: "+stringTokenizer.nextToken()+"\r\n");1090 count-=3;1091 }1092
1093 }else if(st.equals("ALREADY")){1094 JOptionPane.showMessageDialog(loginframe, "账号已登陆!");1095 }else{1096 JOptionPane.showMessageDialog(loginframe, "登陆失败!");1097 }1098 }else if(command.equals("USERZHUCE")){1099 String st =stringTokenizer.nextToken();1100 if(st.equals("OK")){1101 JOptionPane.showMessageDialog(loginframe, "注册成功!");1102
1103 }else if(st.equals("exict")){1104 JOptionPane.showMessageDialog(loginframe, "用户名已存在!");1105 }else{1106 JOptionPane.showMessageDialog(loginframe, "注册失败!");1107 }1108 }else if(command.equals("USERFORGET")){1109 String st =stringTokenizer.nextToken();1110 if(st.equals("OK")){1111 JOptionPane.showMessageDialog(loginframe, "修改密码成功!");1112
1113 }else if(st.equals("YOUXIANG_WRONG")){1114 JOptionPane.showMessageDialog(loginframe, "邮箱错误!");1115 }else if(st.equals("NAME_NO_exict")){1116 JOptionPane.showMessageDialog(loginframe, "用户不存在!");1117 }else{1118 JOptionPane.showMessageDialog(loginframe, "找回密码失败!");1119 }1120 } else if (command.equals("P2P")) {1121 String st =stringTokenizer.nextToken();1122 if(st.equals("OK")){1123 String username =stringTokenizer.nextToken();1124 int serverPort =Integer.parseInt(stringTokenizer.nextToken());1125 String ip =stringTokenizer.nextToken();1126 boolean cn =connectServer_p2p(serverPort,ip,username);1127 if(cn) {1128 JOptionPane.showMessageDialog(frame, "与"+username+"的连接成功,端口号为:"+serverPort+"IP:"+ip );1129 P2P_printWriter.println(frame.getTitle()+"#"+myIP);1130 P2P_printWriter.flush();1131
1132 String msg =textField.getText().trim();1133 P2P_printWriter.println(msg);1134 P2P_printWriter.flush();1135
1136 textArea.append("对 "+username+" 说: "+msg+"\r\n");1137
1138 textField.setText(null);1139 }1140
1141 }else{1142 String username =stringTokenizer.nextToken();1143 JOptionPane.showMessageDialog(frame, "与"+username+"的连接失败!");1144 }1145 } else {//普通消息
1146 textArea.append(message + "\r\n");1147 }1148 } catch(IOException e) {1149 e.printStackTrace();1150 } catch(Exception e) {1151 e.printStackTrace();1152 }1153 }1154 }1155 }1156 }
这个博客展示了如何使用Java编程实现基于TCP协议的聊天应用,包括与MySQL数据库的集成,支持多人聊天、文件传输等功能。博客内容涉及到Java的网络编程、GUI组件以及数据库操作,详细解释了服务器端和客户端的实现逻辑。
538

被折叠的 条评论
为什么被折叠?



