?? chatserver.java
字號:
package chatserver;import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.net.*;import java.io.*;import java.util.*;/** * Title: 服務(wù)器端服務(wù)程序 * Description: 利用Socket建立聊天室服務(wù)器端服務(wù)程序。 * Copyright: Copyright (c) 2002 * Company: 中國農(nóng)業(yè)大學(xué)計算機系 * @author 彭波 * @version 1.0 */ public class chatServer extends JFrame { JPanel contentPane; // 定義圖形界面變量 JMenuBar jMenuBar1 = new JMenuBar(); JMenu jMenuFile = new JMenu(); JMenuItem jMenuFileExit = new JMenuItem(); JMenu jMenuHelp = new JMenu(); JMenuItem jMenuHelpAbout = new JMenuItem(); JLabel statusBar = new JLabel(); BorderLayout borderLayout1 = new BorderLayout(); JPanel jPanel1 = new JPanel(); BorderLayout borderLayout2 = new BorderLayout(); JLabel jLabel1 = new JLabel(); static java.awt.List jList1 = new java.awt.List(13); JScrollPane scrollpane=new JScrollPane(jList1); static Vector clients=new Vector(10); // 用vector向量數(shù)組存儲連接客戶變量 static ServerSocket server=null; // 建立服務(wù)器socket static int active_connects=0; // 用來存儲目前連接的客戶數(shù) static Socket socket=null; // 用來存儲一個套接字連接 public static void main(String[] args) { // 定義main()方法 try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { e.printStackTrace(); } chatServer chatServer1=new chatServer(); // 實例化一個chatServer類 chatServer1.show(); System.out.println("Server starting ..."); try { server=new ServerSocket(8080); // 使用端口8080初始化服務(wù)器套接字 } catch(IOException e) { System.out.println("Error:"+e); } while(true) { if(clients.size()<5) { // 當(dāng)客戶數(shù)小于5個時開始連接 try { socket=server.accept(); // 用來存儲連接上的客戶socket if(socket!=null) { System.out.println(socket+"連接"); // 在服務(wù)器控制臺打印客戶連接信息 } } catch(IOException e) { System.out.println("Error:"+e); } int i=0; do{ ClientEchoThread c=new ClientEchoThread(socket); // 定義并實例化一個ClientEchoThread線程類,對應(yīng)一個客戶連接 clients.addElement(c); // 加入clients數(shù)組中 if(checkName(c)) { // 調(diào)用checkName方法驗證客戶的合法性 int connum=++chatServer1.active_connects; // 定義connum來存儲活動連接數(shù) String constr="目前有"+connum+"客戶相連"; // 在狀態(tài)欄里顯示連接數(shù) chatServer1.statusBar.setText(constr); ClientEchoThread listdata=(ClientEchoThread)clients.elementAt(i); // 連接客戶socket信息存儲進listdata數(shù)組 chatServer1.jList1.addItem(listdata.ip+"連接",i); // 將客戶socket信息寫入list框 c.start(); // 啟動線程 notifyRoom(); // 用notifyRoom方法來監(jiān)視聊天室連接變化 } else { // 客戶名字不合法 c.ps.println("TAKEN"); disconnect(c); } i++; break; } while(i<clients.size()); } else{ // 客戶數(shù)組超過了5個 try{Thread.sleep(200);} catch(InterruptedException e) {} } } // end of while } // end of main method public chatServer(){ // chatServer類構(gòu)造器用來初始化 enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } private void jbInit() throws Exception { contentPane = (JPanel) this.getContentPane(); contentPane.setLayout(borderLayout1); this.setSize(new Dimension(400, 300)); this.setTitle("聊天服務(wù)器端"); statusBar.setText("目前的連接數(shù)為:"); jMenuFile.setText("File"); jMenuFileExit.setText("Exit"); jMenuFileExit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jMenuFileExit_actionPerformed(e); } }); jMenuHelp.setText("Help"); jMenuHelpAbout.setText("About"); jMenuHelpAbout.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jMenuHelpAbout_actionPerformed(e); } }); jPanel1.setLayout(borderLayout2); jLabel1.setText("服務(wù)器端連接客戶"); jMenuFile.add(jMenuFileExit); jMenuHelp.add(jMenuHelpAbout); jMenuBar1.add(jMenuFile); jMenuBar1.add(jMenuHelp); this.setJMenuBar(jMenuBar1); contentPane.add(statusBar, BorderLayout.SOUTH); contentPane.add(jPanel1, BorderLayout.CENTER); jPanel1.add(jLabel1, BorderLayout.NORTH); jPanel1.add(scrollpane, BorderLayout.CENTER); } // end of jbinit public void jMenuFileExit_actionPerformed(ActionEvent e) { // 退出菜單方法 sendClients(new StringBuffer("QUIT")); // 向客戶端發(fā)送斷開連接信息 closeAll(); // 調(diào)用closeAll方法關(guān)閉所有連接 System.exit(0); } public void jMenuHelpAbout_actionPerformed(ActionEvent e) { chatServer_AboutBox dlg = new chatServer_AboutBox(this); Dimension dlgSize = dlg.getPreferredSize(); Dimension frmSize = getSize(); Point loc = getLocation(); dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y); dlg.setModal(true); dlg.show(); } protected void processWindowEvent(WindowEvent e) { // 關(guān)閉服務(wù)器程序要進行的操作 super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { jMenuFileExit_actionPerformed(null); } } public static void notifyRoom(){ // 監(jiān)視連接信息,刷新客戶數(shù)組并刷新客戶端用戶列表信息 StringBuffer people=new StringBuffer("PEOPLE"); for(int i=0;i<clients.size();i++){ ClientEchoThread c=(ClientEchoThread)clients.elementAt(i); people.append(":"+c.name); } sendClients(people); // 用sendClients方法向客戶端發(fā)送信息 } public static synchronized void sendClients(StringBuffer msg) { // 向每個連接的客戶端發(fā)送信息 for(int i=0;i<clients.size();i++) { ClientEchoThread c=(ClientEchoThread)clients.elementAt(i); c.send(msg); } } public static void closeAll(){ // 關(guān)閉所有連接信息 while(clients.size()>0) { // 遍歷clients數(shù)組刪除所有連接客戶信息 ClientEchoThread c=(ClientEchoThread)clients.firstElement(); try{ c.socket.close(); } catch(IOException e) { System.out.println("Error:"+e); } finally { clients.removeElement(c); } } // end of while } // end of closeAll method public static boolean checkName(ClientEchoThread newclient) { // 檢查連接客戶的socket信息是否合法 for(int i=0;i<clients.size();i++) { ClientEchoThread c=(ClientEchoThread)clients.elementAt(i); if((c!=newclient)&&c.equals(newclient.name)) return false; } return(true); } // end of checkName method public static synchronized void disconnect(ClientEchoThread c) { // 斷開單個客戶方法 try { jList1.addItem(c.ip+"斷開連接"); // 在服務(wù)器端程序的list框中顯示斷開信息 chatServer.active_connects--; // 連接數(shù)減1 c.send(new StringBuffer("QUIT")); // 向客戶發(fā)送斷開連接信息 c.socket.close(); } catch(IOException e) { System.out.println("Error:"+e); } finally{ clients.removeElement(c); // 從clients數(shù)組中刪除客戶的相關(guān)socket信息 } } } class ClientEchoThread extends Thread { // 定義ClientEchoThread線程類 Socket socket; // 存儲一個連接客戶的socket信息 String name; // 存儲客戶的連接姓名 String ip; // 存儲客戶的ip信息 DataInputStream dis; // 接收從客戶端發(fā)來的數(shù)據(jù)流 PrintStream ps; // 向客戶端發(fā)送信息的打印流 public void send(StringBuffer msg) { // 向客戶端發(fā)送信息的方法 ps.println(msg); // 打印流發(fā)送信息 ps.flush(); } public ClientEchoThread(Socket s) { // ClientEchoThread線程類的構(gòu)造器 socket=s; try { dis=new DataInputStream(s.getInputStream()); // 存儲客戶socket輸入流,接收發(fā)送的信息 ps=new PrintStream(s.getOutputStream()); // 存儲客戶socket輸出流,向客戶發(fā)送信息 String info=dis.readLine(); // 讀取接收的信息 StringTokenizer stinfo=new StringTokenizer(info,":"); // 用讀取“:”分段字符 String head=stinfo.nextToken(); // 存儲關(guān)鍵字的頭信息 if(stinfo.hasMoreTokens()) name=stinfo.nextToken(); // 關(guān)鍵字后的第二段數(shù)據(jù)是客戶名信息 if(stinfo.hasMoreTokens()) ip=stinfo.nextToken(); // 關(guān)鍵字后的第三段數(shù)據(jù)是客戶ip信息 System.out.println(head); // 在服務(wù)器控制臺打印頭信息 } catch(IOException e) { System.out.println("Error:"+e); } } // end of ClientEchoThread constrator public void run(){ // 定義線程run()方法 while(true) { String line=null; try { line=dis.readLine(); // 讀客戶端發(fā)送的數(shù)據(jù)流 } catch(IOException e) { System.out.println("Error"+e); chatServer.disconnect(this); chatServer.notifyRoom(); return; } if(line==null) { // 客戶已離開 chatServer.disconnect(this); chatServer.notifyRoom(); return; } StringTokenizer st=new StringTokenizer(line,":"); String keyword=st.nextToken(); if(keyword.equals("MSG")) { // 關(guān)鍵字是MSG則是客戶端發(fā)來的聊天信息 StringBuffer msg=new StringBuffer("MSG:"); // 在服務(wù)器端重新建立字符緩沖 msg.append(name); msg.append(st.nextToken("\0")); chatServer.sendClients(msg); // 將某個客戶發(fā)來的信息發(fā)送到每個連接客戶的聊天欄中 } else if(keyword.equals("QUIT")) { // 關(guān)鍵字是QUIT則是客戶端發(fā)來斷開連接的信息 chatServer.disconnect(this); // 服務(wù)器斷開與客戶的連接 chatServer.notifyRoom(); // 繼續(xù)監(jiān)聽聊天室并刷新其他客戶聊天人名列表 this.stop(); } } } } // end of class ClientEchoThread
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -