<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Cyh的博客

    Email:kissyan4916@163.com
    posts - 26, comments - 19, trackbacks - 0, articles - 220

    網絡編程>>聊天室服務器端

    Posted on 2009-12-18 21:51 啥都寫點 閱讀(749) 評論(0)  編輯  收藏 所屬分類: J2SE

      聊天室的服務器端主要用于接收客戶端的連接與斷開請求、廣播聊天室的成員信息、將成員的聊天信息公布給所有成員。
      服務器端在某個端口上開啟ServerSocket,接收客戶端的連接請求。根據客戶端的IP地址和賬號,判斷客戶端是否重復登錄,如果不是,便允許它加入聊天室,并將最新的成員列表發送給所有客戶端。
      每當收到客戶端的聊天信息時,將聊天信息發送給所有客戶端。
      為了處理多個客戶端同時登錄聊天室,采用了多線程的技術,對于每個客戶端,都用一個線程專門處理它。


    /**------------------------------------------------------ChatServer.java--------------------------------------------------------------------*/

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowEvent;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.StringTokenizer;
    import java.util.Vector;

    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.border.TitledBorder;

    /**
     * 聊天室的服務器端程序,GUI界面
     
    */

    public class ChatServer extends JFrame {

        
    // 狀態欄標簽
        static JLabel statusBar = new JLabel();
        
    // 顯示客戶端的連接信息的列表
        static java.awt.List connectInfoList = new java.awt.List(10);

        
    // 保存當前處理客戶端請求的處理器線程
        static Vector clientProcessors = new Vector(10);
        
    // 當前的連接數
        static int activeConnects = 0;

        
    // 構造方法
        public ChatServer()    {
            init();
            
    try {
                
    // 設置界面為系統默認外觀
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                SwingUtilities.updateComponentTreeUI(
    this);
            }
     catch (Exception e) {
                e.printStackTrace();
            }

        }


        
    private void init(){

            
    this.setTitle("聊天室服務器");
            statusBar.setText(
    "");

            
    // 初始化菜單
            JMenu fileMenu = new JMenu();
            fileMenu.setText(
    "文件");
            JMenuItem exitMenuItem 
    = new JMenuItem();
            exitMenuItem.setText(
    "退出");
            exitMenuItem.addActionListener(
    new ActionListener() {
                
    public void actionPerformed(ActionEvent e) {
                    exitActionPerformed(e);
                }

            }
    );
            fileMenu.add(exitMenuItem);
            
            JMenuBar menuBar 
    = new JMenuBar();
            menuBar.add(fileMenu);
            
    this.setJMenuBar(menuBar);

            
    // 將組件進行布局
            JPanel jPanel1 = new JPanel();
            jPanel1.setLayout(
    new BorderLayout());
            JScrollPane pane 
    = new JScrollPane(connectInfoList);
            pane.setBorder(
    new TitledBorder(BorderFactory.createEtchedBorder(
                    Color.white, 
    new Color(134134134)), "客戶端連接信息"));
            jPanel1.add(
    new JScrollPane(pane), BorderLayout.CENTER);
            
            
    this.getContentPane().setLayout(new BorderLayout());
            
    this.getContentPane().add(statusBar, BorderLayout.SOUTH);
            
    this.getContentPane().add(jPanel1, BorderLayout.CENTER);

            
    this.pack();
        }


        
    /**
         * 退出菜單項事件
         * 
    @param e
         
    */

        
    public void exitActionPerformed(ActionEvent e){
            
    //    向客戶端發送斷開連接信息
            sendMsgToClients(new StringBuffer(Constants.QUIT_IDENTIFER)); 
            
    // 關閉所有的連接
            closeAll(); 
            System.exit(
    0);
        }


        
    /**
         * 處理窗口關閉事件
         
    */

        
    protected void processWindowEvent(WindowEvent e) {
            
    super.processWindowEvent(e);
            
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
                exitActionPerformed(
    null);
            }

        }


        
    /**
         * 刷新聊天室,不斷刷新clientProcessors,制造最新的用戶列表
         
    */

        
    public static void notifyRoomPeople(){
            StringBuffer people 
    = new StringBuffer(Constants.PEOPLE_IDENTIFER);
            
    for (int i = 0; i < clientProcessors.size(); i++{
                ClientProcessor c 
    = (ClientProcessor) clientProcessors.elementAt(i);
                people.append(Constants.SEPERATOR).append(c.clientName);
            }

            
    //    用sendClients方法向客戶端發送用戶列表的信息
            sendMsgToClients(people); 
        }


        
    /**
         * 向所有客戶端群發消息
         * 
    @param msg
         
    */

        
    public static synchronized void sendMsgToClients(StringBuffer msg) {
            
    for (int i = 0; i < clientProcessors.size(); i++{
                ClientProcessor c 
    = (ClientProcessor) clientProcessors.elementAt(i);
                System.out.println(
    "send msg: " + msg);
                c.send(msg);
            }

        }


        
    /**
         * 關閉所有連接
         
    */

        
    public static void closeAll(){
            
    while (clientProcessors.size() > 0)    {
                ClientProcessor c 
    = (ClientProcessor) clientProcessors.firstElement();
                
    try {
                    
    // 關閉socket連接和處理線程
                    c.socket.close();
                    c.toStop();
                }
     catch (IOException e) {
                    System.out.println(
    "Error:" + e);
                }
     finally {
                    clientProcessors.removeElement(c);
                }

            }

        }


        
    /**
         * 判斷客戶端是否合法。
         * 不允許同一客戶端重復登陸,所謂同一客戶端是指IP和名字都相同。
         * 
    @param newclient
         * 
    @return
         
    */

        
    public static boolean checkClient(ClientProcessor newclient){
            
    if (clientProcessors.contains(newclient)){
                
    return false;
            }
     else {
                
    return true;
            }

        }


        
    /**
         * 斷開某個連接,并且從連接列表中刪除
         * 
    @param client
         
    */

        
    public static void disconnect(ClientProcessor client){
            disconnect(client, 
    true);
        }

        
        
    /**
         * 斷開某個連接,根據要求決定是否從連接列表中刪除
         * 
    @param client
         * 
    @param toRemoveFromList
         
    */

        
    public static synchronized void disconnect(ClientProcessor client, boolean toRemoveFromList){
            
    try {
                 
    //在服務器端程序的list框中顯示斷開信息
                connectInfoList.add(client.clientIP + "斷開連接");

                ChatServer.activeConnects
    --//將連接數減1
                String constr = "目前有" + ChatServer.activeConnects + "客戶相連";
                statusBar.setText(constr);
                
    //向客戶發送斷開連接信息
                client.send(new StringBuffer(Constants.QUIT_IDENTIFER)); 
                client.socket.close();

            }
     catch (IOException e) {
                System.out.println(
    "Error:" + e);
            }
     finally {
                
    //從clients數組中刪除此客戶的相關socket等信息, 并停止線程。
                if (toRemoveFromList) {
                    clientProcessors.removeElement(client);
                    client.toStop();
                }

            }

        }

        
        
    public static void main(String[] args) {

            ChatServer chatServer1 
    = new ChatServer();
            chatServer1.setVisible(
    true);
            System.out.println(
    "Server starting ");

            ServerSocket server 
    = null;
            
    try {
                
    // 服務器端開始偵聽
                server = new ServerSocket(Constants.SERVER_PORT);
            }
     catch (IOException e) {
                System.out.println(
    "Error:" + e);
                System.exit(
    1);
            }

            
    while (true{
                
    // 如果當前客戶端數小于MAX_CLIENT個時接受連接請求
                if (clientProcessors.size() < Constants.MAX_CLIENT) {
                    Socket socket 
    = null;
                    
    try {
                        
    // 收到客戶端的請求
                        socket = server.accept();
                        
    if (socket != null{
                            System.out.println(socket 
    + "連接");
                        }

                    }
     catch (IOException e) {
                        System.out.println(
    "Error:" + e);
                    }


                    
    //    定義并實例化一個ClientProcessor線程類,用于處理客戶端的消息
                    ClientProcessor c = new ClientProcessor(socket);
                    
    if (checkClient(c)) {
                        
    // 添加到列表
                        clientProcessors.addElement(c);
                        
    // 如果客戶端合法,則繼續
                        int connum = ++ChatServer.activeConnects;
                        
    // 在狀態欄里顯示連接數
                        String constr = "目前有" + connum + "客戶相連";
                        ChatServer.statusBar.setText(constr);
                        
    // 將客戶socket信息寫入list框
                        ChatServer.connectInfoList.add(c.clientIP + "連接"); 
                        c.start();
                        
    // 通知所有客戶端用戶列表發生變化
                        notifyRoomPeople();
                    }
     else {
                        
    //如果客戶端不合法
                        c.ps.println("不允許重復登陸");
                        disconnect(c, 
    false);
                    }


                }
     else {
                    
    //如果客戶端超過了MAX_CLIENT個,則等待一段時間再嘗試接受請求
                    try {
                        Thread.sleep(
    200);
                    }
     catch (InterruptedException e) {
                    }

                }

            }

        }

    }


    /**
     * 處理客戶端發送的請求的線程
     
    */

    class ClientProcessor extends Thread {
        
    //存儲一個連接客戶端的socket信息
        Socket socket;
        
    //存儲客戶端的連接姓名
        String clientName;

        
    //存儲客戶端的ip信息
        String clientIP;
        
        
    //用來實現接受從客戶端發來的數據流
        BufferedReader br;
        
    //用來實現向客戶端發送信息的打印流
        PrintStream ps; 

        
    boolean running = true;
        
        
    /**
         * 構造方法
         * 
    @param s
         
    */

        
    public ClientProcessor(Socket s) {
            socket 
    = s;
            
    try {
                
    //    初始化輸入輸出流
                br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
                ps 
    = new PrintStream(socket.getOutputStream()); 
                
    // 讀取收到的信息,第一條信息是客戶端的名字、IP信息
                String clientInfo = br.readLine();
                
                
    // 讀取信息,根據消息分隔符解析消息
                StringTokenizer stinfo = new StringTokenizer(clientInfo, Constants.SEPERATOR);
                String head 
    = stinfo.nextToken(); 
                
    if (head.equals(Constants.CONNECT_IDENTIFER)){
                    
    if (stinfo.hasMoreTokens()){
                        
    //關鍵字后的第二段數據是客戶名信息
                        clientName = stinfo.nextToken(); 
                    }

                    
    if (stinfo.hasMoreTokens()){
                        
    //關鍵字后的第三段數據是客戶ip信息
                        clientIP = stinfo.nextToken(); 
                    }

                    System.out.println(head); 
    //在控制臺打印頭信息
                }

            }
     catch (IOException e) {
                System.out.println(
    "Error:" + e);
            }

        }


        
    /**
         * 向客戶端發送消息
         * 
    @param msg
         
    */

        
    public void send(StringBuffer msg)    {
            ps.println(msg); 
            ps.flush();
        }

        
        
    //線程運行方法
        public void run() {

            
    while (running) {
                String line 
    = null;
                
    try {
                    
    //讀取客戶端發來的數據流
                    line = br.readLine();

                }
     catch (IOException e) {
                    System.out.println(
    "Error" + e);
                    ChatServer.disconnect(
    this);
                    ChatServer.notifyRoomPeople();
                    
    return;
                }

                 
    //客戶已離開
                if (line == null){
                    ChatServer.disconnect(
    this);
                    ChatServer.notifyRoomPeople();
                    
    return;
                }


                StringTokenizer st 
    = new StringTokenizer(line, Constants.SEPERATOR);
                String keyword 
    = st.nextToken();

                
    // 如果關鍵字是MSG則是客戶端發來的聊天信息
                if (keyword.equals(Constants.MSG_IDENTIFER)){
                    StringBuffer msg 
    = new StringBuffer(Constants.MSG_IDENTIFER).append(Constants.SEPERATOR);
                    msg.append(clientName);
                    msg.append(st.nextToken(
    "\0"));
                    
    //    再將某個客戶發來的聊天信息發送到每個連接客戶的聊天欄中
                    ChatServer.sendMsgToClients(msg); 
                    
                }
     else if (keyword.equals(Constants.QUIT_IDENTIFER)) {
                    
    //    如果關鍵字是QUIT則是客戶端發來斷開連接的信息
                    
                    
    //    服務器斷開與這個客戶的連接
                    ChatServer.disconnect(this); 
                    
    //    繼續監聽聊天室并刷新其他客戶的聊天人名list
                    ChatServer.notifyRoomPeople(); 
                    running 
    = false;
                }

            }

        }

        
        
    public void toStop(){
            running 
    = false;
        }

        
        
    // 覆蓋Object類的equals方法
        public boolean equals(Object obj){
            
    if (obj instanceof ClientProcessor){
                ClientProcessor obj1 
    = (ClientProcessor)obj;
                
    if (obj1.clientIP.equals(this.clientIP) && 
                        (obj1.clientName.equals(
    this.clientName))){
                    
    return true;
                }

            }

            
    return false;
        }

        
        
    // 覆蓋Object類的hashCode方法
        public int hashCode(){
            
    return (this.clientIP + Constants.SEPERATOR + this.clientName).hashCode();
        }

    }
     

    /**---------------------------------Constants.java------------------------------------*/
    /**
     * 定義聊天室程序中用到的常量
     
    */

    public class Constants {

        
    // 服務器的端口號
        public static final int SERVER_PORT = 2525;
        
    public static final int MAX_CLIENT = 10;
        
        
    // 消息標識符與消息體之間的分隔符
        public static final String SEPERATOR = "";
        
        
    // 消息信息的標識符
        public static final String MSG_IDENTIFER = "MSG";
        
    // 用戶列表信息的標識符
        public static final String PEOPLE_IDENTIFER = "PEOPLE";
        
    // 連接服務器信息的標識符
        public static final String CONNECT_IDENTIFER = "INFO";
        
    // 退出信息標識符
        public static final String QUIT_IDENTIFER = "QUIT";
        
    }





                                                                                                           --    學海無涯
            

    主站蜘蛛池模板: 亚洲精品在线免费观看视频| 久久亚洲免费视频| 很黄很色很刺激的视频免费| fc2成年免费共享视频网站| 亚洲色在线无码国产精品不卡| 亚洲成年轻人电影网站www| 亚洲免费人成在线视频观看| 免费a级毛片18以上观看精品| 好吊妞视频免费视频| 黄色片在线免费观看| 亚洲黄色片免费看| 四虎国产成人永久精品免费| a毛片久久免费观看| 亚洲一区二区三区免费| 无遮挡a级毛片免费看| 美女羞羞免费视频网站| 亚洲美国产亚洲AV| 国产日本亚洲一区二区三区 | 日韩亚洲综合精品国产| 亚洲码欧美码一区二区三区| 亚洲天堂免费在线| 亚洲人成7777影视在线观看| 亚洲欧洲日产v特级毛片| 亚洲精品美女在线观看播放| 亚洲精品在线不卡| 亚洲大香人伊一本线| 亚洲性一级理论片在线观看| 亚洲美女自拍视频| 亚洲国产精品专区| 亚洲一卡2卡3卡4卡国产网站| 亚洲乱码在线视频| 一区二区亚洲精品精华液| 亚洲欧洲精品成人久久曰| 亚洲人成无码网站在线观看| 亚洲一区二区三区写真| 亚洲欧美中文日韩视频| 亚洲成a人片在线不卡一二三区 | 女性自慰aⅴ片高清免费| 妞干网在线免费观看| 四虎影视精品永久免费| 亚洲国产精品一区二区九九|