1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > java 通过TCP\UDP 协议实现多人聊天 点对点 文件传送-----分服务器端和客户端...

java 通过TCP\UDP 协议实现多人聊天 点对点 文件传送-----分服务器端和客户端...

时间:2018-10-11 11:44:47

相关推荐

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 .BindException; 13 import .ServerSocket; 14 import .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 44private JFrame frame; 45private JTextArea contentArea; 46private JTextField txt_message; 47private JTextField txt_max; 48private JTextField txt_port; 49private JButton btn_start; 50private JButton btn_stop; 51private JButton btn_send; 52private JButton btn_send_file; 53private JPanel northPanel; 54private JPanel southPanel; 55private JPanel sendPanel; 56private JScrollPane rightPanel; 57private JScrollPane leftPanel; 58private JScrollPane rightPanel2; 59private JSplitPane centerSplit; 60private JSplitPane centerSplit2; 61private JList userList; 62private JList all_userList; 63private DefaultListModel listModel; 64private static DefaultListModel all_listModel; 65 66private ServerSocket serverSocket; 67private ServerThread serverThread; 68private ArrayList<ClientThread> clients;//客户线程数组 69 70private boolean isStart = false;//标志服务器是否启动或关闭 71 72private int sendfor_who = 0;//监听左边jlist,保存给哪个用户发消息 73 74// 主方法,程序执行入口 75public 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*/ 97public 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*/ 113public 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*/ 123public 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*/ 142public 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*/ 186public 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// 构造放法 209public 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 { 340max = Integer.parseInt(txt_max.getText()); 341 } catch (Exception e1) { 342throw new Exception("人数上限为正整数!"); 343 } 344 if (max <= 0) { 345throw new Exception("人数上限为正整数!"); 346 } 347 try { 348port = Integer.parseInt(txt_port.getText()); 349 } catch (Exception e1) { 350throw new Exception("端口号为正整数!"); 351 } 352 if (port <= 0) { 353throw 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*/ 399class 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*/ 417public 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//更新一条数据 437String updateSql = "UPDATE user SET password = '" + codingpassword + "' WHERE Id = " + userid + ""; 438long updateRes = stmt.executeUpdate(updateSql); 439return 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*/ 460public 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*/ 496public 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*/ 535public 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) { 559selectSql = "UPDATE user SET state = 1 WHERE Id = " + id + ""; 560stmt.executeUpdate(selectSql); 561selectSql = "UPDATE user SET serverPort = " + serverPort + " WHERE Id = " + id + ""; 562stmt.executeUpdate(selectSql); 563selectSql = "UPDATE user SET ipAdres = '" + myIP + "' WHERE Id = " + id + ""; 564stmt.executeUpdate(selectSql); 565return 1;//还没有登陆,可以登陆 566 } else { 567return 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 .BindException 584*/ 585public void serverStart(int max, int port) throws .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") 606public 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*/ 641public 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( 649msg, "---"); 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())) { 653clients.get(j).getWriter().println("服务器对你说 " + message); 654clients.get(j).getWriter().flush(); 655flag = 1;//该用户在线状态,已发出去 656break; 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*/ 698public 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*/ 731class 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) {// 如果已达人数上限 746BufferedReader r = new BufferedReader( 747 new InputStreamReader(socket.getInputStream())); 748PrintWriter w = new PrintWriter(socket 749 .getOutputStream()); 750// 接收客户端的基本用户信息 751String inf = r.readLine(); 752StringTokenizer st = new StringTokenizer(inf, "#"); 753User user = new User(st.nextToken(), st.nextToken()); 754// 反馈连接成功信息 755w.println("MAX#服务器:对不起," + user.getName() 756 + user.getIp() + ",服务器在线人数已达上限,请稍后尝试连接!"); 757w.flush(); 758// 释放资源 759r.close(); 760w.close(); 761socket.close(); 762continue; 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*/ 782class 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 { 832contentArea.append(this.getUser().getName() 833 + this.getUser().getIp() + "下线!\r\n"); 834// 断开连接释放资源 835user_offLine(this.getUser().getName()); 836this.getUser().setState(0); 837reader.close(); 838writer.close(); 839socket.close(); 840 841user_name_update();//更新用户状态 842 843 844//反馈用户状态 845String liststr = ""; 846for (int j = 1; j < all_listModel.size(); j++) { 847 liststr += all_listModel.get(j) + "#"; 848} 849// 向所有在线用户发送该用户上线命令 850for (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 857listModel.removeElement(user.getName());// 更新在线列表 858 859// 删除此条客户端服务线程 860for (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")) { 869String username = stringTokenizer.nextToken(); 870String password = stringTokenizer.nextToken(); 871int serverPort = Integer.parseInt(stringTokenizer.nextToken()); 872String myIP = stringTokenizer.nextToken(); 873int i = user_login(username, password,serverPort,myIP); 874if (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")) { 908String username = stringTokenizer.nextToken(); 909String password = stringTokenizer.nextToken(); 910String youxiang = stringTokenizer.nextToken(); 911int i = user_register(username, password, youxiang); 912if (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")) { 925String username = stringTokenizer.nextToken(); 926String youxiang = stringTokenizer.nextToken(); 927String new_password = stringTokenizer.nextToken(); 928int i = user_forget(username, youxiang, new_password); 929if (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")) { 945String username = stringTokenizer.nextToken(); 946int i = get_user_serverPort(username); 947String ip = get_user_serverIP(username); 948if(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")){ 956String username_sent = stringTokenizer.nextToken(); 957String username_receive = stringTokenizer.nextToken(); 958String msg = stringTokenizer.nextToken(); 959send_messageTo_board(username_sent,username_receive,msg); 960System.out.println("离线发送ok"); 961 } else { 962dispatcherMessage(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)) { 984int serverPort = selectRes.getInt("serverPort"); 985return 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)) {1008String serverIP = selectRes.getString("ipAdres");1009return 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"); //链接本地MYSQL1023 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)) {1033String message = selectRes.getString("message");1034String updateSql = "UPDATE user SET message = '' WHERE Id = " + Id + "";1035stmt.executeUpdate(updateSql);1036return 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)) {1063clients.get(i).getWriter().println(owner + " 对你说: " + content);1064clients.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)) {1068clients.get(i).getWriter().println("对 " + source + " 说: " + content);1069clients.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 .ServerSocket; 11 import .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 { 21private Socket clientSocket; 22private String name; 23JFileChooser sourceFileChooser; 24int status; 25JFrame JFrame; 26 27public 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 35public 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 { 73sendFileStream = new FileInputStream(sourceFile); 74 } catch (FileNotFoundException ex) { 75sendToReceiver.flush(); 76sendFileToReceiver.writeByte(0); 77sendFileToReceiver.flush(); 78return; 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 { 88sendFileToReceiver.writeByte(1); 89sendFileToReceiver.flush(); 90while (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} 99sendFileToReceiver.flush();100 } catch (IOException e) {101JOptionPane.showMessageDialog(JFrame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE);102 } finally {103if (sendFileStream != null)104 try {105 sendFileStream.close();106 monitor.close();107 } catch (IOException e) {108 }109 }110 try {111fileReceiverSocket.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 }

View Code

1 //用户信息类 2 public class User{ 3private String name; 4private String ip; 5private int state; 6 7public User(String name, String ip) { 8 this.name = name; 9 this.ip = ip;10 state = 0;11}12 13public String getName() {14 return name;15}16 17public void setName(String name) {18 this.name = name;19}20 21public String getIp() {22 return ip;23}24 25public void setIp(String ip) {26 this.ip = ip;27}28 29public int getState() {30 return state;31}32 33public void setState(int state) {34 this.state = state;35}36 }

View Code

数据库:

是通过MD5加密保存。

客户端代码:

1 package pany; 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 .BindException; 14 import .InetAddress; 15 import .ServerSocket; 16 import .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 36private JPanel sendPanel; 37private JButton btn_send_file; 38private JFrame frame; 39private JList userList; 40private JTextArea textArea; 41private JTextField textField; 42private JTextField txt_port; 43private JTextField txt_hostIp; 44private JTextField txt_name; 45private JButton btn_start; 46private JButton btn_stop; 47private JButton btn_send; 48private JPanel northPanel; 49private JPanel southPanel; 50private JScrollPane rightScroll; 51private JScrollPane leftScroll; 52private JSplitPane centerSplit; 53 54private JPanel logPanle; 55private JFrame loginframe; 56private JLabel label_username; 57private JLabel label_password; 58private JTextField txt_login_name; 59private JTextField txt_password; 60private JTextField txt_login_ip; 61private JTextField txt_login_port; 62private JTextField txt_login_forget; 63private JButton btn_submit; 64private JButton btn_zhuce; 65private JButton btn_forget_pass; 66 67private DefaultListModel listModel; 68private boolean isConnected = false; 69 70private int sendfor_who; 71private int server_port=0; 72 73private ServerSocket serverSocket; 74private ServerThread serverThread; 75private Socket socketfor_p2p; 76private boolean isConnected_p2p = false; 77private ArrayList<ClientThread> clients;//客户线程数组 78private PrintWriter P2P_printWriter;//点对点服务的输出流 79private BufferedReader P2P_bufferReader;//点对点服务的输入流 80private MessageThread_P2P messageThread_for_p2p;// 负责接收p2p消息的线程 81private Map<String, Boolean> P2P_connected_user = new HashMap<String, Boolean>(); 82 83private Socket socket; 84private PrintWriter writer; 85private BufferedReader reader; 86private MessageThread messageThread;// 负责接收消息的线程 87private Map<String, User> onLineUsers = new HashMap<String, User>();// 所有在线用户 88private String myIP = "";//每一个客户端都有唯一的IP地址 89 90// 主方法,程序入口 91public static void main(String[] args) throws BindException { 92 new Client(); 93 94} 95 96class 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*/ 114public 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") 139public 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// 不断接收消息的线程 167class 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 { 203String user = stringTokenizer.nextToken(); 204textArea.append("用户 "+user+" 已下线,p2p服务已关闭!\r\n"); 205closeCon();// 被动的关闭连接 206JOptionPane.showMessageDialog(frame, "用户 "+user+" 已下线,p2p服务已关闭!", "错误", 207 JOptionPane.ERROR_MESSAGE); 208return;// 结束线程 209 } else if (command.equals("FILE")) { 210int portNumber = Integer.parseInt(stringTokenizer.nextToken()); 211String fileName = stringTokenizer.nextToken(); 212long fileSize = Long.parseLong(stringTokenizer.nextToken()); 213String ip = stringTokenizer.nextToken(); 214String Nickname = stringTokenizer.nextToken(); 215ReceiveFileThread receiveFile = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname); 216receiveFile.start(); 217textArea.append("从 "+Nickname+" 接受文件:"+fileName+",大小为:"+fileSize 218 +"ip:"+ip+"port:"+portNumber+"\r\n"); 219 } else {// 普通消息 220textArea.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 .BindException 236*/ 237public void serverStart(int port) throws .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*/ 259class 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 { 324textArea.append("与"+this.getUser().getName() 325 + this.getUser().getIp() + "建立连接成功!\r\n"); 326// 断开连接释放资源 327this.getUser().setState(0); 328reader.close(); 329writer.close(); 330socket.close(); 331 332 } else if (command.equals("FILE")) { 333int portNumber = Integer.parseInt(stringTokenizer.nextToken()); 334String fileName = stringTokenizer.nextToken(); 335long fileSize = Long.parseLong(stringTokenizer.nextToken()); 336String ip = stringTokenizer.nextToken(); 337String Nickname = stringTokenizer.nextToken(); 338ReceiveFileThread receiveFile = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname); 339receiveFile.start(); 340textArea.append("从 "+Nickname+" 接受文件 :"+fileName+",大小为: "+fileSize 341 +" ip: "+ip+" port:"+portNumber+"\r\n"); 342 }else { 343textArea.append(user.getName()+" 对你说: "+message+"\r\n"); 344 } 345 } catch (IOException e) { 346 e.printStackTrace(); 347 } 348 } 349 } 350 351} 352 353/** 354* 服务线程 355*/ 356class 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 381public 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)) { 399SendFileThread sendFile = new SendFileThread(frame, clients.get(i).socket, frame.getTitle(), sourceFileChooser, status); 400sendFile.start(); 401//client端提示 402textArea.append("给 "+user_name+" 发送一个文件:" + sourceFile.getName() + "\r\n"); 403return; 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// 执行发送 420public 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)) { 443clients.get(i).writer_ptp.println("对 "+user_name+" 说: "+message+"\r\n"); 444clients.get(i).writer_ptp.flush(); 445textArea.append("对 "+user_name+" 说: "+message+"\r\n"); 446textField.setText(null); 447return; 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 469public 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("")) { 527JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误", 528 JOptionPane.ERROR_MESSAGE); 529return; 530 } 531 String message2 = txt_password.getText().trim(); 532 if (message2 == null || message2.equals("")) { 533JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误", 534 JOptionPane.ERROR_MESSAGE); 535return; 536 } 537 sendMessage("USERLOGIN#"+message1+"#"+message2+"#"+server_port+"#"+myIP); 538 return; 539 }else{ 540 try { 541try { 542 port = Integer.parseInt(txt_login_port.getText().trim()); 543} catch (NumberFormatException e2) { 544 throw new Exception("端口号不符合要求!端口为整数!"); 545} 546String hostIp = txt_login_ip.getText().trim(); 547String name = txt_login_name.getText().trim(); 548if (name.equals("") || hostIp.equals("")) { 549 throw new Exception("姓名、服务器IP不能为空!"); 550} 551boolean flag = connectServer(port, hostIp, name); 552if (flag == false) { 553 throw new Exception("与服务器连接失败!"); 554} 555frame.setTitle(name); 556listModel.addElement("全部用户"); 557 } catch (Exception exc) { 558JOptionPane.showMessageDialog(loginframe, exc.getMessage(), 559 "错误", JOptionPane.ERROR_MESSAGE); 560return; 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("")) { 596JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误", 597 JOptionPane.ERROR_MESSAGE); 598return; 599 } 600 String message2 = txt_password.getText().trim(); 601 if (message2 == null || message2.equals("")) { 602JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误", 603 JOptionPane.ERROR_MESSAGE); 604return; 605 } 606 String message3 = txt_login_forget.getText().trim(); 607 if (message3 == null || message3.equals("")) { 608JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误", 609 JOptionPane.ERROR_MESSAGE); 610return; 611 } 612 sendMessage("USERZHUCE#"+message1+"#"+message2+"#"+message3); 613 return; 614 }else{ 615 try { 616try { 617 port = Integer.parseInt(txt_login_port.getText().trim()); 618} catch (NumberFormatException e2) { 619 throw new Exception("端口号不符合要求!端口为整数!"); 620} 621String hostIp = txt_login_ip.getText().trim(); 622String name = txt_login_name.getText().trim(); 623if (name.equals("") || hostIp.equals("")) { 624 throw new Exception("姓名、服务器IP不能为空!"); 625} 626boolean flag = connectServer(port, hostIp, name); 627if (flag == false) { 628 throw new Exception("与服务器连接失败!"); 629} 630frame.setTitle(name); 631listModel.addElement("全部用户"); 632 } catch (Exception exc) { 633JOptionPane.showMessageDialog(frame, exc.getMessage(), 634 "错误", JOptionPane.ERROR_MESSAGE); 635return; 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("")) { 679JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误", 680 JOptionPane.ERROR_MESSAGE); 681return; 682 } 683 String message2 = txt_login_forget.getText().trim(); 684 if (message2 == null || message2.equals("")) { 685JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误", 686 JOptionPane.ERROR_MESSAGE); 687return; 688 } 689 String message3 = txt_password.getText().trim(); 690 if (message3 == null || message3.equals("")) { 691JOptionPane.showMessageDialog(logPanle, "修改密码不能为空!", "错误", 692 JOptionPane.ERROR_MESSAGE); 693return; 694 } 695 sendMessage("USERFORGET#"+message1+"#"+message2+"#"+message3); 696 return; 697 }else{ 698 try { 699try { 700 port = Integer.parseInt(txt_login_port.getText().trim()); 701} catch (NumberFormatException e2) { 702 throw new Exception("端口号不符合要求!端口为整数!"); 703} 704String hostIp = txt_login_ip.getText().trim(); 705String name = txt_login_name.getText().trim(); 706if (name.equals("") || hostIp.equals("")) { 707 throw new Exception("姓名、服务器IP不能为空!"); 708} 709boolean flag = connectServer(port, hostIp, name); 710if (flag == false) { 711 throw new Exception("与服务器连接失败!"); 712} 713frame.setTitle(name); 714listModel.addElement("全部用户"); 715 } catch (Exception exc) { 716JOptionPane.showMessageDialog(frame, exc.getMessage(), 717 "错误", JOptionPane.ERROR_MESSAGE); 718return; 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// 构造方法 751public 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) { 882throw 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*/ 916public 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*/ 943public void sendMessage(String message) { 944 writer.println(message); 945 writer.flush(); 946} 947 948/** 949* 客户端主动关闭连接 950*/ 951@SuppressWarnings("deprecation") 952public 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// 不断接收消息的线程 977class 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 {1015textArea.append("服务器已关闭!\r\n");1016closeCon();// 被动的关闭连接1017JOptionPane.showMessageDialog(frame, "服务器已关闭!", "错误",1018 JOptionPane.ERROR_MESSAGE);1019frame.setVisible(false);1020textArea.setText("");1021loginframe.setVisible(true);1022return;// 结束线程1023 } else if (command.equals("ADD")) {// 有用户上线更新在线列表1024String username = "";1025String userIp = "";1026if ((username = stringTokenizer.nextToken()) != null1027 && (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")) {// 有用户下线更新在线列表1033String username = stringTokenizer.nextToken();1034User user = (User) onLineUsers.get(username);1035onLineUsers.remove(user);1036listModel.removeElement(username);1037 } else if (command.equals("USERLIST")) {// 加载在线用户列表1038listModel.removeAllElements();1039listModel.addElement("全部用户");1040StringTokenizer strToken ;1041String user ;// 命令1042int size = Integer1043 .parseInt(stringTokenizer.nextToken());1044String username = null;1045String userIp = null;1046for (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")) {// 人数已达上限1059textArea.append(stringTokenizer.nextToken()1060 + stringTokenizer.nextToken() + "\r\n");1061closeCon();// 被动的关闭连接1062JOptionPane.showMessageDialog(frame, "服务器缓冲区已满!", "错误",1063 JOptionPane.ERROR_MESSAGE);1064return;// 结束线程1065 } else if(command.equals("FILE")){1066int portNumber = Integer.parseInt(stringTokenizer.nextToken());1067String fileName = stringTokenizer.nextToken();1068long fileSize = Long.parseLong(stringTokenizer.nextToken());1069String ip = stringTokenizer.nextToken();1070String Nickname = stringTokenizer.nextToken();1071ReceiveFileThread receiveFile = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname);1072receiveFile.start();1073textArea.append("从"+Nickname+"接受文件:"+fileName+",大小为:"+fileSize1074 +"ip:"+ip+"port:"+portNumber+"\r\n");1075 }else if(command.equals("USERLOGIN")){1076String st = stringTokenizer.nextToken();1077if(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")){1099String st = stringTokenizer.nextToken();1100if(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")){1109String st = stringTokenizer.nextToken();1110if(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")) {1121String st = stringTokenizer.nextToken();1122if(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 {// 普通消息1146textArea.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 pany; 2 3 import javax.swing.*; 4 import java.io.*; 5 import .ServerSocket; 6 import .Socket; 7 8 9 public class SendFileThread extends Thread { 10private Socket clientSocket; 11private String name; 12JFileChooser sourceFileChooser; 13int status; 14JFrame JFrame; 15 16public 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 24public 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 { 62sendFileStream = new FileInputStream(sourceFile); 63 } catch (FileNotFoundException ex) { 64sendToReceiver.flush(); 65sendFileToReceiver.writeByte(0); 66sendFileToReceiver.flush(); 67return; 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 { 77sendFileToReceiver.writeByte(1); 78sendFileToReceiver.flush(); 79while (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} 88sendFileToReceiver.flush(); 89 } catch (IOException e) { 90JOptionPane.showMessageDialog(JFrame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE); 91 } finally { 92if (sendFileStream != null) 93 try { 94 sendFileStream.close(); 95 monitor.close(); 96 } catch (IOException e) { 97 } 98 } 99 try {100fileReceiverSocket.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 }

View Code

1 package pany; 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 .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 { 23private String fileSenderIPAddress; 24private int fileSenderPortNumber; 25private String fileName; 26private long fileSize; 27private String otherNickname; 28JFrame frame; 29JTextArea textArea; 30 31public 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 41public 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) { 75File savedFile = new File(destinationPath.getAbsolutePath()+"\\"+fileName); 76FileOutputStream saveFileStream = new FileOutputStream(savedFile); 77DataOutputStream fileOutput = new DataOutputStream(saveFileStream); 78ProgressMonitorInputStream monitor = new ProgressMonitorInputStream(frame, "接受文件: "+fileName, getFromSender); 79//ProgressMonitor progressMonitor = new ProgressMonitor(null, "Receiving "+fileName, "", 0, (int)fileSize); 80ProgressMonitor progressMonitor = monitor.getProgressMonitor(); 81progressMonitor.setMaximum((int)fileSize); 82 83int read_unit = 500; 84int readed = 0; 85float process = 0; 86try { 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}106catch(IOException e){107 JOptionPane.showMessageDialog(frame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE);108}109finally {110 try {111 fileOutput.close();112 saveFileStream.close();113 progressMonitor.close();114 }115 catch(IOException e){116 }117}118 }119 else {120JOptionPane.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 }

View Code

1 package pany; 2 3 //用户信息类 4 public class User{ 5private String name; 6private String ip; 7private int state; 8 9public User(String name, String ip) {10 this.name = name;11 this.ip = ip;12}13 14public String getName() {15 return name;16}17 18public void setName(String name) {19 this.name = name;20}21 22public String getIp() {23 return ip;24}25 26public void setIp(String ip) {27 this.ip = ip;28}29 30public int getState() {31 return state;32}33 34public void setState(int state){35 this.state=state;36}37 }

View Code

是一次实验课的第一次实验,可能还有bug,请理解!

后期会更新。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。