java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端
java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端
启动界面如下图:
首先启动服务器:
客户端登陆,登陆成功后为:
默认发送是全部用户,是多人发送。 当在边列表里面选择了用户后,可以与此用户建立点对点链接进行聊天,可以发送文件。
用户在线离线状态会实时更新,如果离线,则存为离线消息。当下次上线的时候,会接受到离线消息
从一个用户接受文件的同时,还可以接受从服务器发过来的文件
接受文件完成后,显示记录,并显示保存目录
消息发送演示
服务器端代码:
1 import sun.misc.BASE64Encoder; 2 3 import java.awt.BorderLayout; 4 import java.awt.Color; 5 import java.awt.GridLayout; 6 import java.awt.Toolkit; 7 import java.awt.event.ActionEvent; 8 import java.awt.event.ActionListener; 9 import java.awt.event.WindowAdapter; 10 import java.awt.event.WindowEvent; 11 import java.io.*; 12 import java.net.BindException; 13 import java.net.ServerSocket; 14 import java.net.Socket; 15 import java.security.MessageDigest; 16 import java.security.NoSuchAlgorithmException; 17 import java.sql.Connection; 18 import java.sql.DriverManager; 19 import java.sql.ResultSet; 20 import java.sql.Statement; 21 import java.text.SimpleDateFormat; 22 import java.util.ArrayList; 23 import java.util.Date; 24 import java.util.StringTokenizer; 25 26 import javax.swing.DefaultListModel; 27 import javax.swing.JButton; 28 import javax.swing.JFileChooser; 29 import javax.swing.JFrame; 30 import javax.swing.JLabel; 31 import javax.swing.JList; 32 import javax.swing.JOptionPane; 33 import javax.swing.JPanel; 34 import javax.swing.JScrollPane; 35 import javax.swing.JSplitPane; 36 import javax.swing.JTextArea; 37 import javax.swing.JTextField; 38 import javax.swing.border.TitledBorder; 39 import javax.swing.event.ListSelectionEvent; 40 import javax.swing.event.ListSelectionListener; 41 42 public class Server { 43 44 private JFrame frame; 45 private JTextArea contentArea; 46 private JTextField txt_message; 47 private JTextField txt_max; 48 private JTextField txt_port; 49 private JButton btn_start; 50 private JButton btn_stop; 51 private JButton btn_send; 52 private JButton btn_send_file; 53 private JPanel northPanel; 54 private JPanel southPanel; 55 private JPanel sendPanel; 56 private JScrollPane rightPanel; 57 private JScrollPane leftPanel; 58 private JScrollPane rightPanel2; 59 private JSplitPane centerSplit; 60 private JSplitPane centerSplit2; 61 private JList userList; 62 private JList all_userList; 63 private DefaultListModel listModel; 64 private static DefaultListModel all_listModel; 65 66 private ServerSocket serverSocket; 67 private ServerThread serverThread; 68 private ArrayList<ClientThread> clients;//客户线程数组 69 70 private boolean isStart = false;//标志服务器是否启动或关闭 71 72 private int sendfor_who = 0;//监听左边jlist,保存给哪个用户发消息 73 74 // 主方法,程序执行入口 75 public static void main(String[] args) { 76 77 new Server(); 78 79 try { 80 Connection con = null; //定义一个MYSQL链接对象 81 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 82 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 83 Statement stmt; //创建声明 84 stmt = con.createStatement(); 85 86 } catch (Exception e) { 87 System.out.print("MYSQL ERROR:" + e.getMessage()); 88 } 89 } 90 91 /**利用MD5进行加密 92 * @param str 待加密的字符串 93 * @return 加密后的字符串 94 * @throws NoSuchAlgorithmException 没有这种产生消息摘要的算法 95 * @throws UnsupportedEncodingException 96 */ 97 public String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException { 98 //确定计算方法 99 MessageDigest md5=MessageDigest.getInstance("MD5"); 100 BASE64Encoder base64en = new BASE64Encoder(); 101 //加密后的字符串 102 String newstr=base64en.encode(md5.digest(str.getBytes("utf-8"))); 103 return newstr; 104 } 105 106 /**判断用户密码是否正确 107 * @param newpasswd 用户输入的密码 108 * @param oldpasswd 数据库中存储的密码--用户密码的摘要 109 * @return 110 * @throws NoSuchAlgorithmException 111 * @throws UnsupportedEncodingException 112 */ 113 public boolean checkpassword(String newpasswd,String oldpasswd) throws NoSuchAlgorithmException, UnsupportedEncodingException{ 114 if(EncoderByMd5(newpasswd).equals(oldpasswd)) 115 return true; 116 else 117 return false; 118 } 119 120 /** 121 * 刚服务器突然关闭时,把所有用户状态置为离线 122 */ 123 public void set_user_state_off() { 124 try { 125 Connection con = null; //定义一个MYSQL链接对象 126 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 127 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 128 Statement stmt; //创建声明 129 stmt = con.createStatement(); 130 131 int id = 0; 132 String selectSql = "UPDATE user SET state = 0"; 133 stmt.executeUpdate(selectSql); 134 } catch (Exception e) { 135 System.out.print("MYSQL ERROR:" + e.getMessage()); 136 } 137 } 138 139 /** 140 * 更新用户状态 141 */ 142 public void user_name_update() { 143 144 try { 145 Connection con = null; //定义一个MYSQL链接对象 146 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 147 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 148 Statement stmt; //创建声明 149 stmt = con.createStatement(); 150 151 all_listModel.removeAllElements(); 152 all_listModel.addElement("全部用户"); 153 154 String username_db; 155 int state = 0; 156 //查询用户名 157 String selectSql = "SELECT * FROM user"; 158 ResultSet selectRes = stmt.executeQuery(selectSql); 159 while (selectRes.next()) { //循环输出结果集 160 username_db = selectRes.getString("username"); 161 state = selectRes.getInt("state"); 162 if (state == 1) { 163 all_listModel.addElement(username_db + "---(在线)"); 164 } 165 166 } 167 168 selectRes = stmt.executeQuery(selectSql); 169 while (selectRes.next()) { //循环输出结果集 170 username_db = selectRes.getString("username"); 171 state = selectRes.getInt("state"); 172 if (state == 0) { 173 all_listModel.addElement(username_db + "---(离线)"); 174 } 175 176 } 177 } catch (Exception e) { 178 System.out.print("MYSQL ERROR:" + e.getMessage()); 179 } 180 181 } 182 183 /** 184 * 执行消息发送 185 */ 186 public void send() { 187 if (!isStart) { 188 JOptionPane.showMessageDialog(frame, "服务器还未启动,不能发送消息!", "错误", 189 JOptionPane.ERROR_MESSAGE); 190 return; 191 } 192 // if (clients.size() == 0) { 193 // JOptionPane.showMessageDialog(frame, "没有用户在线,不能发送消息!", "错误", 194 // JOptionPane.ERROR_MESSAGE); 195 // return; 196 // } 197 String message = txt_message.getText().trim(); 198 if (message == null || message.equals("")) { 199 JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误", 200 JOptionPane.ERROR_MESSAGE); 201 return; 202 } 203 sendServerMessage(message, sendfor_who);// 群发服务器消息 204 //contentArea.append("对 "+listModel.getElementAt(sendfor_who)+" 说:" + txt_message.getText() + "\r\n"); 205 txt_message.setText(null); 206 } 207 208 // 构造放法 209 public Server() { 210 SelecTry selectIndex = new SelecTry(); 211 frame = new JFrame("服务器"); 212 contentArea = new JTextArea(); 213 contentArea.setEditable(false); 214 contentArea.setForeground(Color.blue); 215 txt_message = new JTextField(); 216 txt_max = new JTextField("30"); 217 txt_port = new JTextField("6666"); 218 btn_start = new JButton("启动"); 219 btn_stop = new JButton("停止"); 220 btn_send = new JButton("发送"); 221 btn_send_file = new JButton("文件"); 222 btn_stop.setEnabled(false); 223 listModel = new DefaultListModel(); 224 all_listModel = new DefaultListModel(); 225 //listModel.addElement("全部用户"); 226 userList = new JList(all_listModel);//listModel 227 userList.addListSelectionListener(selectIndex); 228 229 user_name_update();//更新用户状态 230 231 // all_userList = new JList(all_listModel); 232 233 southPanel = new JPanel(new BorderLayout()); 234 sendPanel = new JPanel(new BorderLayout()); 235 southPanel.setBorder(new TitledBorder("写消息")); 236 southPanel.add(txt_message, "Center"); 237 sendPanel.add(btn_send, BorderLayout.NORTH); 238 sendPanel.add(btn_send_file, BorderLayout.SOUTH); 239 240 southPanel.add(sendPanel, "East"); 241 242 leftPanel = new JScrollPane(userList); 243 leftPanel.setBorder(new TitledBorder("用户列表")); 244 245 // rightPanel2 = new JScrollPane(all_userList); 246 // rightPanel2.setBorder(new TitledBorder("全部用户")); 247 248 rightPanel = new JScrollPane(contentArea); 249 rightPanel.setBorder(new TitledBorder("消息显示区")); 250 251 centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, 252 rightPanel); 253 centerSplit.setDividerLocation(150); 254 255 // centerSplit2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, centerSplit, 256 // rightPanel2); 257 // centerSplit2.setDividerLocation(450); 258 259 northPanel = new JPanel(); 260 northPanel.setLayout(new GridLayout(1, 6)); 261 northPanel.add(new JLabel(" 人数上限")); 262 northPanel.add(txt_max); 263 northPanel.add(new JLabel(" 端口")); 264 northPanel.add(txt_port); 265 northPanel.add(btn_start); 266 northPanel.add(btn_stop); 267 northPanel.setBorder(new TitledBorder("配置信息")); 268 269 frame.setLayout(new BorderLayout()); 270 frame.add(northPanel, "North"); 271 frame.add(centerSplit, "Center"); 272 //frame.add(rightPanel2,BorderLayout.EAST); 273 frame.add(southPanel, "South"); 274 frame.setSize(600, 400); 275 //frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());//设置全屏 276 int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width; 277 int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height; 278 frame.setLocation((screen_width - frame.getWidth()) / 2, 279 (screen_height - frame.getHeight()) / 2); 280 frame.setVisible(true); 281 282 // 关闭窗口时事件 283 frame.addWindowListener(new WindowAdapter() { 284 public void windowClosing(WindowEvent e) { 285 if (isStart) { 286 closeServer();// 关闭服务器 287 } 288 System.exit(0);// 退出程序 289 } 290 }); 291 292 // 文本框按回车键时事件 293 txt_message.addActionListener(new ActionListener() { 294 public void actionPerformed(ActionEvent e) { 295 send(); 296 } 297 }); 298 299 // 单击发送按钮时事件 300 btn_send.addActionListener(new ActionListener() { 301 public void actionPerformed(ActionEvent arg0) { 302 send(); 303 } 304 }); 305 306 //单机文件按钮时事件 307 btn_send_file.addActionListener(new ActionListener() { 308 public void actionPerformed(ActionEvent arg0) { 309 //文件选择对话框启动,当选择了文件以后给每一个client发送文件 310 JFileChooser sourceFileChooser = new JFileChooser("."); 311 sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 312 int status = sourceFileChooser.showOpenDialog(frame); 313 File sourceFile = new File(sourceFileChooser.getSelectedFile().getPath()); 314 //服务器text area提示 315 contentArea.append("发送文件:" + sourceFile.getName() + "\r\n"); 316 for (int i = clients.size() - 1; i >= 0; i--) { 317 SendFileThread sendFile = new SendFileThread(frame, clients.get(i).socket, "服务器", sourceFileChooser, status); 318 sendFile.start(); 319 //client端提示 320 clients.get(i).getWriter().println("服务器发送一个文件:" + sourceFile.getName() + "(多人发送)"); 321 clients.get(i).getWriter().flush(); 322 } 323 324 } 325 }); 326 327 // 单击启动服务器按钮时事件 328 btn_start.addActionListener(new ActionListener() { 329 public void actionPerformed(ActionEvent e) { 330 331 if (isStart) { 332 JOptionPane.showMessageDialog(frame, "服务器已处于启动状态,不要重复启动!", 333 "错误", JOptionPane.ERROR_MESSAGE); 334 return; 335 } 336 int max;//人数 337 int port;//端口号 338 try { 339 try { 340 max = Integer.parseInt(txt_max.getText()); 341 } catch (Exception e1) { 342 throw new Exception("人数上限为正整数!"); 343 } 344 if (max <= 0) { 345 throw new Exception("人数上限为正整数!"); 346 } 347 try { 348 port = Integer.parseInt(txt_port.getText()); 349 } catch (Exception e1) { 350 throw new Exception("端口号为正整数!"); 351 } 352 if (port <= 0) { 353 throw new Exception("端口号 为正整数!"); 354 } 355 serverStart(max, port); 356 contentArea.append("服务器已成功启动! 人数上限:" + max + ", 端口:" + port 357 + "\r\n"); 358 JOptionPane.showMessageDialog(frame, "服务器成功启动!"); 359 btn_start.setEnabled(false); 360 txt_max.setEnabled(false); 361 txt_port.setEnabled(false); 362 btn_stop.setEnabled(true); 363 listModel.addElement("全部用户"); 364 user_name_update(); 365 } catch (Exception exc) { 366 JOptionPane.showMessageDialog(frame, exc.getMessage(), 367 "错误", JOptionPane.ERROR_MESSAGE); 368 } 369 } 370 }); 371 372 // 单击停止服务器按钮时事件 373 btn_stop.addActionListener(new ActionListener() { 374 public void actionPerformed(ActionEvent e) { 375 if (!isStart) { 376 JOptionPane.showMessageDialog(frame, "服务器还未启动,无需停止!", "错误", 377 JOptionPane.ERROR_MESSAGE); 378 return; 379 } 380 try { 381 closeServer(); 382 btn_start.setEnabled(true); 383 txt_max.setEnabled(true); 384 txt_port.setEnabled(true); 385 btn_stop.setEnabled(false); 386 contentArea.append("服务器成功停止!\r\n"); 387 JOptionPane.showMessageDialog(frame, "服务器成功停止!"); 388 } catch (Exception exc) { 389 JOptionPane.showMessageDialog(frame, "停止服务器发生异常!", "错误", 390 JOptionPane.ERROR_MESSAGE); 391 } 392 } 393 }); 394 } 395 396 /** 397 * 监听左边jlist选择的是哪一个用户 398 */ 399 class SelecTry implements ListSelectionListener { 400 int change = 0, who; 401 402 public void valueChanged(ListSelectionEvent e) { 403 //System.out.println("you selected:"+listModel.getElementAt(userList.getSelectedIndex())); 404 sendfor_who = userList.getSelectedIndex(); 405 } 406 407 } 408 409 /** 410 * 找回密码模块 411 * 412 * @param username 413 * @param youxiang 414 * @param new_password 415 * @return 416 */ 417 public int user_forget(String username, String youxiang, String new_password) { 418 try { 419 Connection con = null; //定义一个MYSQL链接对象 420 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 421 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 422 Statement stmt; //创建声明 423 stmt = con.createStatement(); 424 425 String codingpassword = EncoderByMd5(new_password); 426 427 //查询数据,不能有相同的用户名 428 String selectSql = "SELECT * FROM user"; 429 ResultSet selectRes = stmt.executeQuery(selectSql); 430 while (selectRes.next()) { //循环输出结果集 431 int userid = selectRes.getInt("Id"); 432 String username_db = selectRes.getString("username"); 433 String youxiang_db = selectRes.getString("youxiang"); 434 if (username.equals(username_db)) { 435 if (youxiang_db.equals(youxiang)) { 436 //更新一条数据 437 String updateSql = "UPDATE user SET password = '" + codingpassword + "' WHERE Id = " + userid + ""; 438 long updateRes = stmt.executeUpdate(updateSql); 439 return 1; 440 } 441 442 } 443 } 444 return 0; 445 } catch (Exception e) { 446 System.out.print("MYSQL ERROR:" + e.getMessage()); 447 } 448 return 0; 449 } 450 451 452 /** 453 * 注册模块 454 * 455 * @param username 456 * @param password 457 * @param youxiang 458 * @return 459 */ 460 public int user_register(String username, String password, String youxiang) { 461 462 try { 463 Connection con = null; //定义一个MYSQL链接对象 464 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 465 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 466 Statement stmt; //创建声明 467 stmt = con.createStatement(); 468 469 String codingPassword = EncoderByMd5(password); 470 471 //查询数据,不能有相同的用户名 472 String selectSql = "SELECT * FROM user"; 473 ResultSet selectRes = stmt.executeQuery(selectSql); 474 while (selectRes.next()) { //循环输出结果集 475 String username_db = selectRes.getString("username"); 476 if (username.equals(username_db)) { 477 return 2; 478 } 479 } 480 //新增一条数据 481 stmt.executeUpdate("INSERT INTO user (username, password,youxiang) VALUES ('" + username + "', '" + codingPassword + "','" + youxiang + "')"); 482 all_listModel.addElement(username); 483 return 1; 484 } catch (Exception e) { 485 System.out.print("MYSQL ERROR:" + e.getMessage()); 486 } 487 return 0; 488 } 489 490 /** 491 * 当有用户下线时,在服务器改变状态 492 * 493 * @param name 494 * @return 495 */ 496 public int user_offLine(String name) { 497 try { 498 Connection con = null; //定义一个MYSQL链接对象 499 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 500 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 501 Statement stmt; //创建声明 502 stmt = con.createStatement(); 503 504 // 505 String username_fromDb; 506 int id = 0; 507 String selectSql = "SELECT * FROM user"; 508 ResultSet selectRes = stmt.executeQuery(selectSql); 509 while (selectRes.next()) { //循环输出结果集 510 username_fromDb = selectRes.getString("username"); 511 id = selectRes.getInt("Id"); 512 if (name.equals(username_fromDb)) { 513 selectSql = "UPDATE user SET state = 0 WHERE Id = " + id + ""; 514 stmt.executeUpdate(selectSql); 515 selectSql = "UPDATE user SET serverPort = 0 WHERE Id = " + id + ""; 516 stmt.executeUpdate(selectSql); 517 selectSql = "UPDATE user SET ipAdres = '' WHERE Id = " + id + ""; 518 stmt.executeUpdate(selectSql); 519 return 1; 520 } 521 } 522 } catch (Exception e) { 523 System.out.print("MYSQL ERROR:" + e.getMessage()); 524 } 525 return 0; 526 } 527 528 /** 529 * 登陆模块 530 * 531 * @param username 532 * @param password 533 * @return 534 */ 535 public int user_login(String username, String password,int serverPort,String myIP) { 536 try { 537 Connection con = null; //定义一个MYSQL链接对象 538 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 539 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 540 Statement stmt; //创建声明 541 stmt = con.createStatement(); 542 543 544 // 545 String username_fromDb; 546 String password_fromDb; 547 String codingNewPassword; 548 int state = 0, id = 0; 549 String selectSql = "SELECT * FROM user"; 550 ResultSet selectRes = stmt.executeQuery(selectSql); 551 while (selectRes.next()) { //循环输出结果集 552 username_fromDb = selectRes.getString("username"); 553 password_fromDb = selectRes.getString("password"); 554 codingNewPassword = EncoderByMd5(password); 555 id = selectRes.getInt("Id"); 556 state = selectRes.getInt("state"); 557 if (username.equals(username_fromDb) && codingNewPassword.equals(password_fromDb)) { 558 if (state == 0) { 559 selectSql = "UPDATE user SET state = 1 WHERE Id = " + id + ""; 560 stmt.executeUpdate(selectSql); 561 selectSql = "UPDATE user SET serverPort = " + serverPort + " WHERE Id = " + id + ""; 562 stmt.executeUpdate(selectSql); 563 selectSql = "UPDATE user SET ipAdres = '" + myIP + "' WHERE Id = " + id + ""; 564 stmt.executeUpdate(selectSql); 565 return 1;//还没有登陆,可以登陆 566 } else { 567 return 2;//已登陆状态,无法登陆 568 } 569 570 } 571 } 572 } catch (Exception e) { 573 System.out.print("MYSQL ERROR:" + e.getMessage()); 574 } 575 return 0; 576 } 577 578 /** 579 * 启动服务器 580 * 581 * @param max 582 * @param port 583 * @throws java.net.BindException 584 */ 585 public void serverStart(int max, int port) throws java.net.BindException { 586 try { 587 clients = new ArrayList<ClientThread>(); 588 serverSocket = new ServerSocket(port); 589 serverThread = new ServerThread(serverSocket, max); 590 serverThread.start(); 591 isStart = true; 592 } catch (BindException e) { 593 isStart = false; 594 throw new BindException("端口号已被占用,请换一个!"); 595 } catch (Exception e1) { 596 e1.printStackTrace(); 597 isStart = false; 598 throw new BindException("启动服务器异常!"); 599 } 600 } 601 602 /** 603 * 关闭服务器 604 */ 605 @SuppressWarnings("deprecation") 606 public void closeServer() { 607 try { 608 if (serverThread != null) 609 serverThread.stop();// 停止服务器线程 610 611 for (int i = clients.size() - 1; i >= 0; i--) { 612 // 给所有在线用户发送关闭命令 613 clients.get(i).getWriter().println("CLOSE"); 614 clients.get(i).getWriter().flush(); 615 // 释放资源 616 clients.get(i).stop();// 停止此条为客户端服务的线程 617 clients.get(i).reader.close(); 618 clients.get(i).writer.close(); 619 clients.get(i).socket.close(); 620 clients.remove(i); 621 } 622 if (serverSocket != null) { 623 serverSocket.close();// 关闭服务器端连接 624 } 625 listModel.removeAllElements();// 清空用户列表 626 isStart = false; 627 set_user_state_off(); 628 user_name_update(); 629 } catch (IOException e) { 630 e.printStackTrace(); 631 isStart = true; 632 } 633 } 634 635 /** 636 * 群发服务器消息 637 * 638 * @param message 639 * @param who 640 */ 641 public void sendServerMessage(String message, int who) { 642 if (who == 0) { 643 StringTokenizer stringTokenizer; 644 int flag = 0; 645 for (int i = all_listModel.size(); i > 0; i--) { 646 flag = 0; 647 String msg = all_listModel.getElementAt(i - 1) + ""; 648 stringTokenizer = new StringTokenizer( 649 msg, "---"); 650 String user_name = stringTokenizer.nextToken(); 651 for (int j = clients.size() - 1; j >= 0; j--) { 652 if (user_name.equals(clients.get(j).getUser().getName())) { 653 clients.get(j).getWriter().println("服务器对你说 " + message); 654 clients.get(j).getWriter().flush(); 655 flag = 1;//该用户在线状态,已发出去 656 break; 657 } 658 } 659 if (flag == 0) { 660 //用户离线状态,则留言 661 send_messageTo_board("服务器", user_name, message); 662 } 663 } 664 contentArea.append("对 全部用户 发送:" + message + "\r\n"); 665 } else { 666 int flag = 0; 667 String msg = "" + all_listModel.getElementAt(who); 668 StringTokenizer stringTokenizer = new StringTokenizer( 669 msg, "---"); 670 String user_name = stringTokenizer.nextToken(); 671 for (int i = clients.size() - 1; i >= 0; i--) { 672 if (user_name.equals(clients.get(i).getUser().getName())) { 673 clients.get(i).getWriter().println("服务器对你说 " + message); 674 clients.get(i).getWriter().flush(); 675 flag = 1;//该用户在线状态,已发出去 676 break; 677 } 678 } 679 if (flag == 0) { 680 // JOptionPane.showMessageDialog(frame, "该用户不在线,已存为留言板!", "错误", 681 // JOptionPane.ERROR_MESSAGE); 682 send_messageTo_board("服务器", user_name, message); 683 contentArea.append("对 " + user_name + " 留言:" + message + "\r\n"); 684 } else { 685 contentArea.append("对 " + user_name + " 说:" + message + "\r\n"); 686 } 687 } 688 689 } 690 691 /** 692 * 用户不在线时,离线消息保存到服务器里面 693 * @param send_from 694 * @param send_for 695 * @param message 696 * @return 697 */ 698 public int send_messageTo_board(String send_from, String send_for, String message) { 699 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式 700 String msg = send_from + "#" + df.format(new Date()) + "#" + message + "#"; 701 try { 702 Connection con = null; //定义一个MYSQL链接对象 703 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 704 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 705 Statement stmt; //创建声明 706 stmt = con.createStatement(); 707 708 //查询数据,不能有相同的用户名 709 String selectSql = "SELECT * FROM user"; 710 ResultSet selectRes = stmt.executeQuery(selectSql); 711 while (selectRes.next()) { //循环输出结果集 712 int Id = selectRes.getInt("Id"); 713 String username_db = selectRes.getString("username"); 714 if (send_for.equals(username_db)) { 715 String old_message = selectRes.getString("message"); 716 String updateSql = "UPDATE user SET message = '" + old_message + msg + "' WHERE Id = " + Id + ""; 717 stmt.executeUpdate(updateSql); 718 return 1; 719 } 720 } 721 return 0; 722 } catch (Exception e) { 723 System.out.print("MYSQL ERROR:" + e.getMessage()); 724 } 725 return 0; 726 } 727 728 /** 729 * 服务器线程 730 */ 731 class ServerThread extends Thread { 732 private ServerSocket serverSocket; 733 private int max;// 人数上限 734 735 // 服务器线程的构造方法 736 public ServerThread(ServerSocket serverSocket, int max) { 737 this.serverSocket = serverSocket; 738 this.max = max; 739 } 740 741 public void run() { 742 while (true) {// 不停的等待客户端的链接 743 try { 744 Socket socket = serverSocket.accept(); 745 if (clients.size() == max) {// 如果已达人数上限 746 BufferedReader r = new BufferedReader( 747 new InputStreamReader(socket.getInputStream())); 748 PrintWriter w = new PrintWriter(socket 749 .getOutputStream()); 750 // 接收客户端的基本用户信息 751 String inf = r.readLine(); 752 StringTokenizer st = new StringTokenizer(inf, "#"); 753 User user = new User(st.nextToken(), st.nextToken()); 754 // 反馈连接成功信息 755 w.println("MAX#服务器:对不起," + user.getName() 756 + user.getIp() + ",服务器在线人数已达上限,请稍后尝试连接!"); 757 w.flush(); 758 // 释放资源 759 r.close(); 760 w.close(); 761 socket.close(); 762 continue; 763 } 764 ClientThread client = new ClientThread(socket); 765 client.start();// 开启对此客户端服务的线程 766 client.getUser().setState(1);//在线状态 767 clients.add(client); 768 listModel.addElement(client.getUser().getName());// 更新在线列表 769 contentArea.append(client.getUser().getName() 770 + client.getUser().getIp() + "上线!\r\n"); 771 // user_name_update(); 772 } catch (IOException e) { 773 e.printStackTrace(); 774 } 775 } 776 } 777 } 778 779 /** 780 * 为一个客户端服务的线程 781 */ 782 class ClientThread extends Thread { 783 private Socket socket; 784 private BufferedReader reader; 785 private PrintWriter writer; 786 private User user; 787 788 public BufferedReader getReader() { 789 return reader; 790 } 791 792 public PrintWriter getWriter() { 793 return writer; 794 } 795 796 public User getUser() { 797 return user; 798 } 799 800 // 客户端线程的构造方法 801 public ClientThread(Socket socket) { 802 try { 803 this.socket = socket; 804 reader = new BufferedReader(new InputStreamReader(socket 805 .getInputStream())); 806 writer = new PrintWriter(socket.getOutputStream()); 807 // 接收客户端的基本用户信息 808 String inf = reader.readLine(); 809 StringTokenizer st = new StringTokenizer(inf, "#"); 810 user = new User(st.nextToken(), st.nextToken()); 811 // 反馈连接成功信息 812 writer.println(user.getName() + user.getIp() + "与服务器连接成功!"); 813 writer.flush(); 814 815 816 } catch (IOException e) { 817 e.printStackTrace(); 818 } 819 } 820 821 @SuppressWarnings("deprecation") 822 public void run() {// 不断接收客户端的消息,进行处理。 823 String message = null; 824 while (true) { 825 try { 826 message = reader.readLine();// 接收客户端消息 827 StringTokenizer stringTokenizer = new StringTokenizer( 828 message, "#"); 829 String command = stringTokenizer.nextToken();// 命令 830 if (command.equals("CLOSE"))// 下线命令 831 { 832 contentArea.append(this.getUser().getName() 833 + this.getUser().getIp() + "下线!\r\n"); 834 // 断开连接释放资源 835 user_offLine(this.getUser().getName()); 836 this.getUser().setState(0); 837 reader.close(); 838 writer.close(); 839 socket.close(); 840 841 user_name_update();//更新用户状态 842 843 844 //反馈用户状态 845 String liststr = ""; 846 for (int j = 1; j < all_listModel.size(); j++) { 847 liststr += all_listModel.get(j) + "#"; 848 } 849 // 向所有在线用户发送该用户上线命令 850 for (int j = clients.size()-1 ; j >= 0; j--) { 851 clients.get(j).getWriter().println( 852 "USERLIST#" + all_listModel.size() + "#" + liststr); 853 clients.get(j).getWriter().flush(); 854 } 855 //user_name_update();//更新用户状态 856 857 listModel.removeElement(user.getName());// 更新在线列表 858 859 // 删除此条客户端服务线程 860 for (int i = clients.size() - 1; i >= 0; i--) { 861 if (clients.get(i).getUser() == user) { 862 ClientThread temp = clients.get(i); 863 clients.remove(i);// 删除此用户的服务线程 864 temp.stop();// 停止这条服务线程 865 return; 866 } 867 } 868 } else if (command.equals("USERLOGIN")) { 869 String username = stringTokenizer.nextToken(); 870 String password = stringTokenizer.nextToken(); 871 int serverPort = Integer.parseInt(stringTokenizer.nextToken()); 872 String myIP = stringTokenizer.nextToken(); 873 int i = user_login(username, password,serverPort,myIP); 874 if (1 == i) { 875 user_name_update(); 876 String msg = get_message(username); 877 if (msg.equals("")) { 878 writer.println("USERLOGIN#OK#"); 879 writer.flush(); 880 } else { 881 writer.println("USERLOGIN#OK#" + msg); 882 writer.flush(); 883 } 884 885 886 //反馈用户状态 887 String temp = ""; 888 for (int j = 1; j < all_listModel.size(); j++) { 889 temp += all_listModel.get(j) + "#"; 890 } 891 // 向所有在线用户发送该用户上线命令 892 for (int j = clients.size()-1 ; j >= 0; j--) { 893 clients.get(j).getWriter().println( 894 "USERLIST#" + all_listModel.size() + "#" + temp); 895 clients.get(j).getWriter().flush(); 896 } 897 898 } else if (2 == i) { 899 writer.println("USERLOGIN#ALREADY"); 900 writer.flush(); 901 } else { 902 writer.println("USERLOGIN#NO"); 903 writer.flush(); 904 905 } 906 //user_name_update(); 907 } else if (command.equals("USERZHUCE")) { 908 String username = stringTokenizer.nextToken(); 909 String password = stringTokenizer.nextToken(); 910 String youxiang = stringTokenizer.nextToken(); 911 int i = user_register(username, password, youxiang); 912 if (1 == i) { 913 writer.println("USERZHUCE#OK"); 914 writer.flush(); 915 contentArea.append("有新用户注册! 用户名:" + username + "\r\n"); 916 user_name_update();//更新用户状态 917 } else if (i == 2) { 918 writer.println("USERZHUCE#exict"); 919 writer.flush(); 920 } else { 921 writer.println("USERZHUCE#NO"); 922 writer.flush(); 923 } 924 } else if (command.equals("USERFORGET")) { 925 String username = stringTokenizer.nextToken(); 926 String youxiang = stringTokenizer.nextToken(); 927 String new_password = stringTokenizer.nextToken(); 928 int i = user_forget(username, youxiang, new_password); 929 if (1 == i) { 930 //JOptionPane.showMessageDialog(frame, "登陆成功!" ); 931 writer.println("USERFORGET#OK"); 932 writer.flush(); 933 contentArea.append(" 用户:" + username + " 修改密码!\r\n"); 934 } else if (i == 2) { 935 writer.println("USERFORGET#YOUXIANG_WRONG"); 936 writer.flush(); 937 } else if (i == 3) { 938 writer.println("USERFORGET#NAME_NO_exict"); 939 writer.flush(); 940 } else { 941 writer.println("USERFORGET#NO"); 942 writer.flush(); 943 } 944 } else if (command.equals("P2P")) { 945 String username = stringTokenizer.nextToken(); 946 int i = get_user_serverPort(username); 947 String ip = get_user_serverIP(username); 948 if(i!=0){ 949 writer.println("P2P#OK#"+username+"#"+i+"#"+ip); 950 writer.flush(); 951 }else{ 952 writer.println("P2P#NO#"+username); 953 writer.flush(); 954 } 955 }else if(command.equals("LIXIAN")){ 956 String username_sent = stringTokenizer.nextToken(); 957 String username_receive = stringTokenizer.nextToken(); 958 String msg = stringTokenizer.nextToken(); 959 send_messageTo_board(username_sent,username_receive,msg); 960 System.out.println("离线发送ok"); 961 } else { 962 dispatcherMessage(message);// 转发消息 963 } 964 } catch (IOException e) { 965 e.printStackTrace(); 966 } 967 } 968 } 969 970 public int get_user_serverPort(String user_name){ 971 try { 972 Connection con = null; //定义一个MYSQL链接对象 973 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 974 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 975 Statement stmt; //创建声明 976 stmt = con.createStatement(); 977 978 //查询数据,不能有相同的用户名 979 String selectSql = "SELECT * FROM user"; 980 ResultSet selectRes = stmt.executeQuery(selectSql); 981 while (selectRes.next()) { //循环输出结果集 982 String username_db = selectRes.getString("username"); 983 if (user_name.equals(username_db)) { 984 int serverPort = selectRes.getInt("serverPort"); 985 return serverPort; 986 } 987 } 988 } catch (Exception e) { 989 System.out.print("MYSQL ERROR:" + e.getMessage()); 990 } 991 return 0; 992 } 993 994 public String get_user_serverIP(String user_name){ 995 try { 996 Connection con = null; //定义一个MYSQL链接对象 997 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 998 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 999 Statement stmt; //创建声明 1000 stmt = con.createStatement(); 1001 1002 //查询数据,不能有相同的用户名 1003 String selectSql = "SELECT * FROM user"; 1004 ResultSet selectRes = stmt.executeQuery(selectSql); 1005 while (selectRes.next()) { //循环输出结果集 1006 String username_db = selectRes.getString("username"); 1007 if (user_name.equals(username_db)) { 1008 String serverIP = selectRes.getString("ipAdres"); 1009 return serverIP; 1010 } 1011 } 1012 } catch (Exception e) { 1013 System.out.print("MYSQL ERROR:" + e.getMessage()); 1014 } 1015 return ""; 1016 } 1017 1018 public String get_message(String name) { 1019 try { 1020 Connection con = null; //定义一个MYSQL链接对象 1021 Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动 1022 con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL 1023 Statement stmt; //创建声明 1024 stmt = con.createStatement(); 1025 1026 //查询数据,不能有相同的用户名 1027 String selectSql = "SELECT * FROM user"; 1028 ResultSet selectRes = stmt.executeQuery(selectSql); 1029 while (selectRes.next()) { //循环输出结果集 1030 int Id = selectRes.getInt("Id"); 1031 String username_db = selectRes.getString("username"); 1032 if (name.equals(username_db)) { 1033 String message = selectRes.getString("message"); 1034 String updateSql = "UPDATE user SET message = '' WHERE Id = " + Id + ""; 1035 stmt.executeUpdate(updateSql); 1036 return message; 1037 } 1038 } 1039 return ""; 1040 } catch (Exception e) { 1041 System.out.print("MYSQL ERROR:" + e.getMessage()); 1042 } 1043 return ""; 1044 } 1045 1046 // 转发消息 1047 public void dispatcherMessage(String message) { 1048 StringTokenizer stringTokenizer = new StringTokenizer(message, "#"); 1049 String source = stringTokenizer.nextToken(); 1050 String owner = stringTokenizer.nextToken(); 1051 String content = stringTokenizer.nextToken(); 1052 1053 if (owner.equals("ALL")) {// 群发 1054 message = source + "说:" + content; 1055 contentArea.append(message + "\r\n"); 1056 for (int i = clients.size() - 1; i >= 0; i--) { 1057 clients.get(i).getWriter().println(message + "(多人发送)"); 1058 clients.get(i).getWriter().flush(); 1059 } 1060 } else { 1061 for (int i = clients.size() - 1; i >= 0; i--) { 1062 if (clients.get(i).user.getName().equals(owner)) { 1063 clients.get(i).getWriter().println(owner + " 对你说: " + content); 1064 clients.get(i).getWriter().flush(); 1065 //contentArea.append(owner+" 对 "+ clients.get(i).user.getName()+ " 说 :"+ content+"\r\n"); 1066 } 1067 if (clients.get(i).user.getName().equals(source)) { 1068 clients.get(i).getWriter().println("对 " + source + " 说: " + content); 1069 clients.get(i).getWriter().flush(); 1070 } 1071 } 1072 } 1073 } 1074 } 1075 }
1 import java.io.BufferedOutputStream; 2 import java.io.BufferedReader; 3 import java.io.DataOutputStream; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.FileNotFoundException; 7 import java.io.IOException; 8 import java.io.InputStreamReader; 9 import java.io.PrintWriter; 10 import java.net.ServerSocket; 11 import java.net.Socket; 12 13 import javax.swing.JFileChooser; 14 import javax.swing.JFrame; 15 import javax.swing.JOptionPane; 16 import javax.swing.ProgressMonitor; 17 import javax.swing.ProgressMonitorInputStream; 18 19 20 public class SendFileThread extends Thread { 21 private Socket clientSocket; 22 private String name; 23 JFileChooser sourceFileChooser; 24 int status; 25 JFrame JFrame; 26 27 public SendFileThread(JFrame frame, Socket socket, String name, JFileChooser sourceFileChooser, int status) { 28 this.clientSocket = socket; 29 this.name = name; 30 this.sourceFileChooser = sourceFileChooser; 31 this.status = status; 32 this.JFrame = frame; 33 } 34 35 public void run() { 36 // JFileChooser sourceFileChooser = new JFileChooser("."); 37 // sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 38 // int status = sourceFileChooser.showOpenDialog(null); 39 if (status == JFileChooser.APPROVE_OPTION) { 40 File sourceFile = new File(sourceFileChooser.getSelectedFile().getPath()); 41 String sourceFilePath = sourceFile.getAbsolutePath(); 42 String fileName = sourceFile.getName(); 43 //System.out.println(sourceFilePath+"\\"+fileName); 44 try { 45 PrintWriter sendToClient = new PrintWriter(clientSocket.getOutputStream()); 46 BufferedReader getFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 47 ServerSocket fileSenderSocket = null; 48 try { 49 fileSenderSocket = new ServerSocket(0); 50 } catch (IOException ex1) { 51 JOptionPane.showMessageDialog(JFrame, "无法分配端口以发送此文件!", "错误", JOptionPane.ERROR_MESSAGE); 52 } 53 sendToClient.println("FILE#" + fileSenderSocket.getLocalPort() + "#" + fileName + "#" 54 + String.valueOf(sourceFile.length()) + "#" + clientSocket.getInetAddress().getHostAddress() + "#" + name); 55 sendToClient.flush(); 56 //System.out.println("Sender: "+fileSenderSocket.getLocalSocketAddress()); 57 Socket fileReceiverSocket = fileSenderSocket.accept(); 58 59 BufferedReader getFromReceiver = null; 60 PrintWriter sendToReceiver = null; 61 try { 62 getFromReceiver = new BufferedReader(new InputStreamReader(fileReceiverSocket.getInputStream())); 63 sendToReceiver = new PrintWriter(fileReceiverSocket.getOutputStream()); 64 } catch (IOException ex) { 65 } finally { 66 } 67 String judge = getFromReceiver.readLine(); 68 if (judge.equals("accepted")) { 69 DataOutputStream sendFileToReceiver = new DataOutputStream(new BufferedOutputStream(fileReceiverSocket.getOutputStream())); 70 ProgressMonitorInputStream monitor; 71 FileInputStream sendFileStream = null; 72 try { 73 sendFileStream = new FileInputStream(sourceFile); 74 } catch (FileNotFoundException ex) { 75 sendToReceiver.flush(); 76 sendFileToReceiver.writeByte(0); 77 sendFileToReceiver.flush(); 78 return; 79 } 80 monitor = new ProgressMonitorInputStream(JFrame, "正在发送: " + fileName, sendFileStream); 81 ProgressMonitor progressMonitor = monitor.getProgressMonitor(); 82 83 int read_unit = 500; 84 long fileSize = monitor.available(); 85 int readed = 0; 86 byte[] data = new byte[read_unit]; 87 try { 88 sendFileToReceiver.writeByte(1); 89 sendFileToReceiver.flush(); 90 while (monitor.available() > 0) { 91 int in = monitor.read(data); 92 readed += in; 93 float process = (float) readed / fileSize * 100; 94 progressMonitor.setNote(process + " % 完成"); 95 if (in > 0) { 96 sendFileToReceiver.write(data, 0, in); 97 } 98 } 99 sendFileToReceiver.flush(); 100 } catch (IOException e) { 101 JOptionPane.showMessageDialog(JFrame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE); 102 } finally { 103 if (sendFileStream != null) 104 try { 105 sendFileStream.close(); 106 monitor.close(); 107 } catch (IOException e) { 108 } 109 } 110 try { 111 fileReceiverSocket.close(); 112 } catch (IOException ex1) { 113 } 114 } else if (judge.equals("refused")) { 115 JOptionPane.showMessageDialog(JFrame, "对方拒绝接受文件 " + fileName, "错误!", JOptionPane.INFORMATION_MESSAGE); 116 } 117 118 } catch (IOException ex) { 119 } finally { 120 } 121 } 122 } 123 }
1 //用户信息类 2 public class User{ 3 private String name; 4 private String ip; 5 private int state; 6 7 public User(String name, String ip) { 8 this.name = name; 9 this.ip = ip; 10 state = 0; 11 } 12 13 public String getName() { 14 return name; 15 } 16 17 public void setName(String name) { 18 this.name = name; 19 } 20 21 public String getIp() { 22 return ip; 23 } 24 25 public void setIp(String ip) { 26 this.ip = ip; 27 } 28 29 public int getState() { 30 return state; 31 } 32 33 public void setState(int state) { 34 this.state = state; 35 } 36 }
数据库:
是通过MD5加密保存。
客户端代码:
1 package com.company; 2 3 import java.awt.BorderLayout; 4 import java.awt.Color; 5 import java.awt.Font; 6 import java.awt.GridLayout; 7 import java.awt.Toolkit; 8 import java.awt.event.ActionEvent; 9 import java.awt.event.ActionListener; 10 import java.awt.event.WindowAdapter; 11 import java.awt.event.WindowEvent; 12 import java.io.*; 13 import java.net.BindException; 14 import java.net.InetAddress; 15 import java.net.ServerSocket; 16 import java.net.Socket; 17 import java.sql.Connection; 18 import java.sql.DriverManager; 19 import java.sql.ResultSet; 20 import java.sql.Statement; 21 import java.util.ArrayList; 22 import java.util.HashMap; 23 import java.util.Map; 24 import java.util.StringTokenizer; 25 26 import javax.swing.*; 27 import javax.swing.border.TitledBorder; 28 import javax.swing.event.ListSelectionEvent; 29 import javax.swing.event.ListSelectionListener; 30 31 //import socket_chat_server.Server.ClientThread; 32 //import socket_chat_server.Server.SelecTry; 33 34 public class Client{ 35 36 private JPanel sendPanel; 37 private JButton btn_send_file; 38 private JFrame frame; 39 private JList userList; 40 private JTextArea textArea; 41 private JTextField textField; 42 private JTextField txt_port; 43 private JTextField txt_hostIp; 44 private JTextField txt_name; 45 private JButton btn_start; 46 private JButton btn_stop; 47 private JButton btn_send; 48 private JPanel northPanel; 49 private JPanel southPanel; 50 private JScrollPane rightScroll; 51 private JScrollPane leftScroll; 52 private JSplitPane centerSplit; 53 54 private JPanel logPanle; 55 private JFrame loginframe; 56 private JLabel label_username; 57 private JLabel label_password; 58 private JTextField txt_login_name; 59 private JTextField txt_password; 60 private JTextField txt_login_ip; 61 private JTextField txt_login_port; 62 private JTextField txt_login_forget; 63 private JButton btn_submit; 64 private JButton btn_zhuce; 65 private JButton btn_forget_pass; 66 67 private DefaultListModel listModel; 68 private boolean isConnected = false; 69 70 private int sendfor_who; 71 private int server_port=0; 72 73 private ServerSocket serverSocket; 74 private ServerThread serverThread; 75 private Socket socketfor_p2p; 76 private boolean isConnected_p2p = false; 77 private ArrayList<ClientThread> clients;//客户线程数组 78 private PrintWriter P2P_printWriter;//点对点服务的输出流 79 private BufferedReader P2P_bufferReader;//点对点服务的输入流 80 private MessageThread_P2P messageThread_for_p2p;// 负责接收p2p消息的线程 81 private Map<String, Boolean> P2P_connected_user = new HashMap<String, Boolean>(); 82 83 private Socket socket; 84 private PrintWriter writer; 85 private BufferedReader reader; 86 private MessageThread messageThread;// 负责接收消息的线程 87 private Map<String, User> onLineUsers = new HashMap<String, User>();// 所有在线用户 88 private String myIP = "";//每一个客户端都有唯一的IP地址 89 90 // 主方法,程序入口 91 public static void main(String[] args) throws BindException { 92 new Client(); 93 94 } 95 96 class SelecTry implements ListSelectionListener 97 { 98 int change=0,who; 99 public void valueChanged(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 * @param port 111 * @param hostIp 112 * @param name 113 */ 114 public boolean connectServer_p2p(int port, String hostIp, String name) { 115 // 连接服务器 116 try { 117 socketfor_p2p = new Socket(hostIp, port);// 根据端口号和服务器ip建立连接 118 P2P_printWriter = new PrintWriter(socketfor_p2p.getOutputStream()); 119 P2P_bufferReader = new BufferedReader(new InputStreamReader(socketfor_p2p 120 .getInputStream())); 121 122 messageThread_for_p2p = new MessageThread_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地址为:" + hostIp 129 + " 的服务连接失败!" + "\r\n"); 130 isConnected_p2p = false;// 未连接上 131 return false; 132 } 133 } 134 135 /** 136 * 关闭服务 137 */ 138 @SuppressWarnings("deprecation") 139 public void closeServer() { 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 extends Thread { 168 private BufferedReader reader_ptp; 169 170 // 接收消息线程的构造方法 171 public MessageThread_P2P(BufferedReader reader) { 172 this.reader_ptp = reader; 173 174 } 175 176 // 被动的关闭连接 177 public synchronized void closeCon() throws Exception { 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 void run() { 194 String message = ""; 195 while (true) { 196 try { 197 message = reader_ptp.readLine(); 198 StringTokenizer stringTokenizer = new StringTokenizer( 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 = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname); 216 receiveFile.start(); 217 textArea.append("从 "+Nickname+" 接受文件:"+fileName+",大小为:"+fileSize 218 +"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 * @param port 235 * @throws java.net.BindException 236 */ 237 public void serverStart(int port) throws java.net.BindException { 238 try { 239 clients = new ArrayList<ClientThread>(); 240 serverSocket = new ServerSocket(port); 241 serverThread = new ServerThread(serverSocket); 242 serverThread.start(); 243 server_port = serverSocket.getLocalPort(); 244 InetAddress addr = InetAddress.getLocalHost(); 245 myIP = addr.getHostAddress();//获得本机IP 246 // 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 extends Thread { 260 private Socket socket; 261 private BufferedReader reader_ptp; 262 private PrintWriter writer_ptp; 263 private User user; 264 265 public BufferedReader getReader() { 266 return reader_ptp; 267 } 268 269 public PrintWriter getWriter() { 270 return writer_ptp; 271 } 272 273 public User getUser() { 274 return user; 275 } 276 277 // 客户端线程的构造方法 278 public ClientThread(Socket socket) { 279 try { 280 this.socket = socket; 281 reader_ptp = new BufferedReader(new InputStreamReader(socket 282 .getInputStream())); 283 writer_ptp = new PrintWriter(socket.getOutputStream()); 284 285 // 接收客户端的基本用户信息 286 String inf = reader_ptp.readLine(); 287 StringTokenizer st = new StringTokenizer(inf, "#"); 288 user = new User(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() + "/" + clients 297 // .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 = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname); 339 receiveFile.start(); 340 textArea.append("从 "+Nickname+" 接受文件 :"+fileName+",大小为: "+fileSize 341 +" 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 extends Thread { 357 private ServerSocket serverSocket; 358 359 // 服务器线程的构造方法 360 public ServerThread(ServerSocket serverSocket) { 361 this.serverSocket = serverSocket; 362 } 363 364 public void run() { 365 while (true) {// 不停的等待客户端的链接 366 try { 367 Socket socket = serverSocket.accept(); 368 ClientThread client = new ClientThread(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 void sendFile() { 382 //文件选择对话框启动,当选择了文件以后给每一个client发送文件 383 JFileChooser sourceFileChooser = new JFileChooser("."); 384 sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 385 int status = sourceFileChooser.showOpenDialog(frame); 386 File sourceFile = new File(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 = new SendFileThread(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 = new SendFileThread(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 void send() { 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 void Login(){ 470 Font font = new Font("宋体", 1, 16); 471 472 logPanle = new JPanel(); 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(new ActionListener() { 510 public void actionPerformed(ActionEvent e) { 511 int port; 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(new ActionListener() { 572 public void actionPerformed(ActionEvent e) { 573 int port; 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(new ActionListener() { 654 public void actionPerformed(ActionEvent e) { 655 int port; 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(new WindowAdapter() { 740 public void windowClosing(WindowEvent e) { 741 if (isConnected) { 742 closeConnection();// 关闭连接 743 closeServer();//关闭服务程序 744 } 745 System.exit(0);// 退出程序 746 } 747 }); 748 } 749 750 // 构造方法 751 public Client() throws BindException { 752 753 serverStart(0); 754 755 SelecTry selectIndex=new SelecTry(); 756 757 textArea = new JTextArea(); 758 textArea.setEditable(false); 759 textArea.setForeground(Color.blue); 760 textField = new JTextField(); 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 = new DefaultListModel(); 769 userList = new JList(listModel); 770 //listModel.addElement("全部用户"); 771 userList.addListSelectionListener(selectIndex); 772 northPanel = new JPanel(); 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 = new JScrollPane(textArea); 785 rightScroll.setBorder(new TitledBorder("消息显示区")); 786 leftScroll = new JScrollPane(userList); 787 leftScroll.setBorder(new TitledBorder("用户列表")); 788 southPanel = new JPanel(new BorderLayout()); 789 sendPanel = new JPanel(new BorderLayout()); 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 = new JSplitPane(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(new BorderLayout()); 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(new ActionListener() { 817 public void actionPerformed(ActionEvent arg0) { 818 send(); 819 } 820 }); 821 822 // 单击发送按钮时事件 823 btn_send.addActionListener(new ActionListener() { 824 public void actionPerformed(ActionEvent e) { 825 send(); 826 } 827 }); 828 829 //单机文件按钮时事件 830 btn_send_file.addActionListener(new ActionListener() { 831 public void actionPerformed(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(new ActionListener() { 872 public void actionPerformed(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(new WindowAdapter() { 898 public void windowClosing(WindowEvent e) { 899 if (isConnected) { 900 closeConnection();// 关闭连接 901 closeServer();//关闭服务程序 902 } 903 System.exit(0);// 退出程序 904 } 905 }); 906 Login(); 907 } 908 909 /** 910 * 连接服务器 911 * 912 * @param port 913 * @param hostIp 914 * @param name 915 */ 916 public boolean connectServer(int port, String hostIp, String name) { 917 // 连接服务器 918 try { 919 socket = new Socket(hostIp, port);// 根据端口号和服务器ip建立连接 920 writer = new PrintWriter(socket.getOutputStream()); 921 reader = new BufferedReader(new InputStreamReader(socket 922 .getInputStream())); 923 // 发送客户端用户基本信息(用户名和ip地址) 924 sendMessage(name + "#" + socket.getLocalAddress().toString()); 925 // 开启接收消息的线程 926 messageThread = new MessageThread(reader, textArea); 927 messageThread.start(); 928 isConnected = true;// 已经连接上了 929 return true; 930 } catch (Exception e) { 931 textArea.append("与端口号为:" + port + " IP地址为:" + hostIp 932 + " 的服务器连接失败!" + "\r\n"); 933 isConnected = false;// 未连接上 934 return false; 935 } 936 } 937 938 /** 939 * 发送消息 940 * 941 * #param message 942 */ 943 public void sendMessage(String message) { 944 writer.println(message); 945 writer.flush(); 946 } 947 948 /** 949 * 客户端主动关闭连接 950 */ 951 @SuppressWarnings("deprecation") 952 public synchronized boolean closeConnection() { 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 extends Thread { 978 private BufferedReader reader; 979 private JTextArea textArea; 980 981 // 接收消息线程的构造方法 982 public MessageThread(BufferedReader reader, JTextArea textArea) { 983 this.reader = reader; 984 this.textArea = textArea; 985 } 986 987 // 被动的关闭连接 988 public synchronized void closeCon() throws Exception { 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 void run() { 1006 String message = ""; 1007 while (true) { 1008 try { 1009 message = reader.readLine(); 1010 StringTokenizer stringTokenizer = new StringTokenizer( 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 = new User(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 = Integer 1043 .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 = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname); 1072 receiveFile.start(); 1073 textArea.append("从"+Nickname+"接受文件:"+fileName+",大小为:"+fileSize 1074 +"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 }
1 package com.company; 2 3 import javax.swing.*; 4 import java.io.*; 5 import java.net.ServerSocket; 6 import java.net.Socket; 7 8 9 public class SendFileThread extends Thread { 10 private Socket clientSocket; 11 private String name; 12 JFileChooser sourceFileChooser; 13 int status; 14 JFrame JFrame; 15 16 public SendFileThread(JFrame frame, Socket socket, String name, JFileChooser sourceFileChooser, int status) { 17 this.clientSocket = socket; 18 this.name = name; 19 this.sourceFileChooser = sourceFileChooser; 20 this.status = status; 21 this.JFrame = frame; 22 } 23 24 public void run() { 25 // JFileChooser sourceFileChooser = new JFileChooser("."); 26 // sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 27 // int status = sourceFileChooser.showOpenDialog(null); 28 if (status == JFileChooser.APPROVE_OPTION) { 29 File sourceFile = new File(sourceFileChooser.getSelectedFile().getPath()); 30 String sourceFilePath = sourceFile.getAbsolutePath(); 31 String fileName = sourceFile.getName(); 32 //System.out.println(sourceFilePath+"\\"+fileName); 33 try { 34 PrintWriter sendToClient = new PrintWriter(clientSocket.getOutputStream()); 35 BufferedReader getFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 36 ServerSocket fileSenderSocket = null; 37 try { 38 fileSenderSocket = new ServerSocket(0); 39 } catch (IOException ex1) { 40 JOptionPane.showMessageDialog(JFrame, "无法分配端口以发送此文件!", "错误", JOptionPane.ERROR_MESSAGE); 41 } 42 sendToClient.println("FILE#" + fileSenderSocket.getLocalPort() + "#" + fileName + "#" 43 + String.valueOf(sourceFile.length()) + "#" + clientSocket.getLocalAddress() + "#" + name); 44 sendToClient.flush(); 45 //System.out.println("Sender: "+fileSenderSocket.getLocalSocketAddress()); 46 Socket fileReceiverSocket = fileSenderSocket.accept(); 47 48 BufferedReader getFromReceiver = null; 49 PrintWriter sendToReceiver = null; 50 try { 51 getFromReceiver = new BufferedReader(new InputStreamReader(fileReceiverSocket.getInputStream())); 52 sendToReceiver = new PrintWriter(fileReceiverSocket.getOutputStream()); 53 } catch (IOException ex) { 54 } finally { 55 } 56 String judge = getFromReceiver.readLine(); 57 if (judge.equals("accepted")) { 58 DataOutputStream sendFileToReceiver = new DataOutputStream(new BufferedOutputStream(fileReceiverSocket.getOutputStream())); 59 ProgressMonitorInputStream monitor; 60 FileInputStream sendFileStream = null; 61 try { 62 sendFileStream = new FileInputStream(sourceFile); 63 } catch (FileNotFoundException ex) { 64 sendToReceiver.flush(); 65 sendFileToReceiver.writeByte(0); 66 sendFileToReceiver.flush(); 67 return; 68 } 69 monitor = new ProgressMonitorInputStream(JFrame, "正在发送: " + fileName, sendFileStream); 70 ProgressMonitor progressMonitor = monitor.getProgressMonitor(); 71 72 int read_unit = 500; 73 long fileSize = monitor.available(); 74 int readed = 0; 75 byte[] data = new byte[read_unit]; 76 try { 77 sendFileToReceiver.writeByte(1); 78 sendFileToReceiver.flush(); 79 while (monitor.available() > 0) { 80 int in = monitor.read(data); 81 readed += in; 82 float process = (float) readed / fileSize * 100; 83 progressMonitor.setNote(process + " % 完成"); 84 if (in > 0) { 85 sendFileToReceiver.write(data, 0, in); 86 } 87 } 88 sendFileToReceiver.flush(); 89 } catch (IOException e) { 90 JOptionPane.showMessageDialog(JFrame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE); 91 } finally { 92 if (sendFileStream != null) 93 try { 94 sendFileStream.close(); 95 monitor.close(); 96 } catch (IOException e) { 97 } 98 } 99 try { 100 fileReceiverSocket.close(); 101 } catch (IOException ex1) { 102 } 103 } else if (judge.equals("refused")) { 104 JOptionPane.showMessageDialog(JFrame, "对方拒绝接受文件 " + fileName, "错误!", JOptionPane.INFORMATION_MESSAGE); 105 } 106 107 } catch (IOException ex) { 108 } finally { 109 } 110 } 111 } 112 }
1 package com.company; 2 import java.io.BufferedInputStream; 3 import java.io.BufferedOutputStream; 4 import java.io.BufferedReader; 5 import java.io.DataInputStream; 6 import java.io.DataOutputStream; 7 import java.io.File; 8 import java.io.FileOutputStream; 9 import java.io.IOException; 10 import java.io.InputStreamReader; 11 import java.io.PrintWriter; 12 import java.net.Socket; 13 14 import javax.swing.JFileChooser; 15 import javax.swing.JFrame; 16 import javax.swing.JOptionPane; 17 import javax.swing.JTextArea; 18 import javax.swing.ProgressMonitor; 19 import javax.swing.ProgressMonitorInputStream; 20 21 22 public class ReceiveFileThread extends Thread { 23 private String fileSenderIPAddress; 24 private int fileSenderPortNumber; 25 private String fileName; 26 private long fileSize; 27 private String otherNickname; 28 JFrame frame; 29 JTextArea textArea; 30 31 public ReceiveFileThread(JTextArea textArea,JFrame frame,String ip, int port_number, String file_name, long file_size, String other_nickname) { 32 this.fileSenderIPAddress = ip; 33 this.fileSenderPortNumber = port_number; 34 this.fileName = file_name; 35 this.fileSize = file_size; 36 this.otherNickname = other_nickname; 37 this.frame = frame; 38 this.textArea = textArea; 39 } 40 41 public void run() { 42 Socket fileSenderSocket = null; 43 try { 44 fileSenderSocket = new Socket(fileSenderIPAddress, fileSenderPortNumber); 45 } 46 catch(IOException ex) { 47 JOptionPane.showMessageDialog(frame, "无法连接到服务器接收文件!", "错误", JOptionPane.ERROR_MESSAGE); 48 } 49 finally { 50 } 51 DataInputStream getFromSender = null; 52 DataOutputStream sendToSender = null; 53 try { 54 getFromSender = new DataInputStream(new BufferedInputStream(fileSenderSocket.getInputStream())); 55 sendToSender = new DataOutputStream(new BufferedOutputStream(fileSenderSocket.getOutputStream())); 56 BufferedReader getInfoFromSender =new BufferedReader(new InputStreamReader(getFromSender)); 57 58 int permit = JOptionPane.showConfirmDialog(frame, "接受文件:"+fileName+" 从 "+otherNickname+"?", "文件传输请求:", JOptionPane.YES_NO_OPTION); 59 if(permit == JOptionPane.YES_OPTION) { 60 sendToSender.writeBytes("accepted\n"); 61 sendToSender.flush(); 62 63 JFileChooser destinationFileChooser = new JFileChooser("."); 64 destinationFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 65 int status = destinationFileChooser.showSaveDialog(frame); 66 File destinationPath = null; 67 if (status == JFileChooser.APPROVE_OPTION) { 68 destinationPath = new File(destinationFileChooser.getSelectedFile().getPath()); 69 //String destinationFile = destinationPath.getAbsolutePath()+"\\"+fileName; 70 //System.out.println(destinationFilePath); 71 } 72 try { 73 byte judge = getFromSender.readByte(); 74 if (judge > 0) { 75 File savedFile = new File(destinationPath.getAbsolutePath()+"\\"+fileName); 76 FileOutputStream saveFileStream = new FileOutputStream(savedFile); 77 DataOutputStream fileOutput = new DataOutputStream(saveFileStream); 78 ProgressMonitorInputStream monitor = new ProgressMonitorInputStream(frame, "接受文件: "+fileName, getFromSender); 79 //ProgressMonitor progressMonitor = new ProgressMonitor(null, "Receiving "+fileName, "", 0, (int)fileSize); 80 ProgressMonitor progressMonitor = monitor.getProgressMonitor(); 81 progressMonitor.setMaximum((int)fileSize); 82 83 int read_unit = 500; 84 int readed = 0; 85 float process = 0; 86 try { 87 while (true) { 88 byte[] data = new byte[read_unit]; 89 int in = monitor.read(data); 90 readed += in; 91 process = (float) readed / fileSize * 100; 92 progressMonitor.setNote(process+" % 完成"); 93 progressMonitor.setProgress(readed); 94 if (in <= 0) { 95 break; 96 } 97 fileOutput.write(data,0,in); 98 } 99 100 fileOutput.flush(); 101 if(savedFile.length() < fileSize) { 102 JOptionPane.showMessageDialog(frame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE); 103 } 104 textArea.append("接受文件:"+fileName+" 保存地址:"+destinationPath+"\r\n"); 105 } 106 catch(IOException e){ 107 JOptionPane.showMessageDialog(frame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE); 108 } 109 finally { 110 try { 111 fileOutput.close(); 112 saveFileStream.close(); 113 progressMonitor.close(); 114 } 115 catch(IOException e){ 116 } 117 } 118 } 119 else { 120 JOptionPane.showMessageDialog(frame, "源文件没有找到!", "错误", JOptionPane.ERROR_MESSAGE); 121 } 122 } 123 catch(IOException e){ 124 } 125 finally { 126 fileSenderSocket.close(); 127 } 128 } 129 else if(permit == JOptionPane.NO_OPTION) { 130 sendToSender.writeBytes("refused\n"); 131 sendToSender.flush(); 132 } 133 } 134 catch(IOException ex) { 135 } 136 finally { 137 } 138 //System.out.println("Receiver: "+fileReceiverSocket.getRemoteSocketAddress()); 139 } 140 141 }
1 package com.company; 2 3 //用户信息类 4 public class User{ 5 private String name; 6 private String ip; 7 private int state; 8 9 public User(String name, String ip) { 10 this.name = name; 11 this.ip = ip; 12 } 13 14 public String getName() { 15 return name; 16 } 17 18 public void setName(String name) { 19 this.name = name; 20 } 21 22 public String getIp() { 23 return ip; 24 } 25 26 public void setIp(String ip) { 27 this.ip = ip; 28 } 29 30 public int getState() { 31 return state; 32 } 33 34 public void setState(int state){ 35 this.state=state; 36 } 37 }
是一次实验课的第一次实验,可能还有bug,请理解!
后期会更新。