java線上聊天項目0.7版 串連多個用戶端問題,開啟多個用戶端後伺服器端只接收到一個 對各種異常的補充處理,線上聊天0.7

來源:互聯網
上載者:User

java線上聊天項目0.7版 串連多個用戶端問題,開啟多個用戶端後伺服器端只接收到一個 對各種異常的補充處理,線上聊天0.7

問題的原因是

while(connected) {
String str=dis.readUTF();
System.out.println(str);
}

不斷迴圈執行,一直在死迴圈擷取socket發送的資訊,

使得前面的語句

s = ss.accept();
connected=true;

服務端接收新的用戶端不能再被執行

解決的方法——通過多線程技術

當獲得一個socket後,則開啟一個多線程,讓

while(connected) {
String str=dis.readUTF();
System.out.println(str);
}

迴圈讀取操作在多線程中完成

這樣每個socket獲得之後都在各自的現成中完成自己的迴圈讀取

 

具體方法:

首先在主函數main中建立一個關於線程的內部類,因為這個類外部其他類不需要,所以弄成內部類

解決問題後:

伺服器端代碼有較大改動,當中遇到各種異常逐一解決,邏輯思路上不複雜,細節上注意解決了

先開啟用戶端的各種異常

用戶端關閉後的異常提示

服務端增加了ServerSocket的關閉

服務端增加線程處理後無效果的調試——根據socket closed異常查明是

在內部類Client中while迴圈寫在了try的外邊,導致socket已經被關閉,但迴圈依然在盡心,不斷提示出錯

0.7版的最終伺服器端代碼如下:

package com.swift;import java.io.DataInputStream;import java.io.EOFException;import java.io.IOException;import java.net.BindException;import java.net.ServerSocket;import java.net.Socket;public class ChatServer {    public static void main(String[] args) {        new ChatServer().fun();    }    private void fun() {        boolean started = false;        ServerSocket ss = null;        Socket s = null;        try {            ss = new ServerSocket(8888);            started = true;        } catch (BindException e) {            System.out.println("連接埠使用中......");        } catch (IOException e1) {            e1.printStackTrace();        }        try {            while (started) {                s = ss.accept();                System.out.println("a client connected success");                Client c = new Client(s);                new Thread(c).start();            }        } catch (EOFException e) {            System.out.println("client has closed.");        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                ss.close();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    class Client implements Runnable {        private Socket s;        private DataInputStream dis;        private boolean connected = false;        public Client(Socket s) {            this.s = s;            try {                this.dis = new DataInputStream(s.getInputStream());                connected = true;            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }        @Override        public void run() {            try {//注意:要包括while迴圈,如果try在while迴圈裡,則出現socket closed異常                while (connected) {                    String str = dis.readUTF();                    System.out.println(str);                }            } catch (IOException e) {                e.printStackTrace();            } finally {                if (dis != null) {                    try {                        dis.close();                    } catch (IOException e) {                        e.printStackTrace();                    }                }                if (s != null) {                    try {                        s.close();                    } catch (IOException e) {                        e.printStackTrace();                    }                }            }        }    }}

0.7版本的用戶端代碼改動不大,代碼如下:

package com.swift;import java.awt.BorderLayout;import java.awt.Color;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.DataOutputStream;import java.io.IOException;import java.net.ConnectException;import java.net.Socket;import java.net.UnknownHostException;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;public class ChatClientFrame extends JFrame {    private static final long serialVersionUID = -118470059355655240L;    Socket s = null;    DataOutputStream dos = null;    JLabel label_shang = new JLabel();    JLabel label_xia = new JLabel();    JTextField tf = new JTextField(38);    JTextArea ta = new JTextArea(15, 50);    JButton button = new JButton();    public ChatClientFrame() {        setBounds(200, 200, 500, 400);        setTitle("用戶端聊天工具 —— 0.7");        // 對視窗進行大的布局,分為三行一列,在pBasic面板上添加三個面板shang zhong xia        JPanel pBasic = new JPanel();        pBasic.setLayout(new BorderLayout());// 不設定預設也是這種配置模式        setContentPane(pBasic);// 把面板放在視窗上,不記得用this.關鍵字        JPanel shang = new JPanel();        JPanel zhong = new JPanel();        JPanel xia = new JPanel();        // 設定JPanel面板的大小        shang.setSize(470, 25);        zhong.setSize(470, 180);        xia.setSize(470, 40);        pBasic.add(shang, BorderLayout.NORTH);        pBasic.add(zhong, BorderLayout.CENTER);        pBasic.add(xia, BorderLayout.SOUTH);        shang.setBackground(Color.red);        zhong.setBackground(Color.yellow);        xia.setBackground(Color.blue);        label_shang.setText("聊天記錄");        shang.add(label_shang);        ta.setLineWrap(true);// 自動換行        JScrollPane scroll = new JScrollPane(ta);// 增加捲軸,以便不增加行數        zhong.add(scroll);        label_xia.setText("輸入資訊");        xia.add(label_xia, BorderLayout.WEST);        /*         * 增加功能,視窗監聽事件,視窗開啟時設定游標焦點在tf文本域中         */        this.addWindowListener(new WindowAdapter() {            @Override            public void windowOpened(WindowEvent e) {                tf.requestFocus();            }        });        xia.add(tf, BorderLayout.CENTER);        button.setText("發送");        xia.add(button, BorderLayout.EAST);        final class ShareListener implements ActionListener {            @Override            public void actionPerformed(ActionEvent e) {                String taText = ta.getText();                String tfText = tf.getText() + "\r\n";                String tfText1 = tf.getText();                ta.setText(taText + tfText);                tf.setText("");                // 當斷行符號或發送按鈕時,tfText發送到伺服器                try {                    dos.writeUTF(tfText1);                    dos.flush();                } catch (IOException e1) {                    e1.printStackTrace();                }            }        }        button.addActionListener(new ShareListener());        tf.addActionListener(new ShareListener());        // 通過壓縮自動調整各個面板        pack();        this.addWindowListener(new WindowAdapter() {            @Override            public void windowClosing(WindowEvent e) {                disconnect();                System.exit(0);            }        });        setVisible(true);        // 建立表單直接調用串連伺服器        connect();    }    public void connect() {        try {            s = new Socket("127.0.0.1", 8888);            System.out.println("connected!");            dos = new DataOutputStream(s.getOutputStream());        } catch (ConnectException e) {            System.out.println("服務端異常.........");            System.out.println("請確認服務端是否開啟.........");        } catch (IOException e) {            e.printStackTrace();        }    }    public void disconnect() {        try {            if (dos != null)                dos.close();            if (s != null)                s.close();        } catch (IOException e) {            e.printStackTrace();        }    }    public static void main(String[] args) {        new ChatClientFrame();    }}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.