1. 程式人生 > >Android Socket 聊天室

Android Socket 聊天室

專案地址:https://github.com/SunnyLine/Android-Socket-ChatRoom
部分截圖:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

以下為程式碼邏輯部分
Java: 監聽某個埠,有使用者訪問時,將這個Socket放入到一個集合中作為一個使用者組,並監聽這個Socket的訊息。收到任意一個Socket的訊息後,再將此訊息分發給使用者組的每一個成員。
Android:使用Socket連線指定IP指定埠,連線成功後傳送一條資訊給伺服器,伺服器會將之轉發給其他人,其他人就可以知道組內有新使用者加入的資訊。離開此頁面時也要傳送給伺服器一條離開的資訊,伺服器會告知其他使用者。在子執行緒中監聽伺服器傳送的資料進行顯示。

Java程式碼如下:

public class Main {

    private static final int PORT = 9999;
    private static List<Socket> mList = new ArrayList<Socket>();
    private static ServerSocket server = null;
    private static ExecutorService mExecutorService = null; //thread pool

    public static void main
(String[] args) { try { server = new ServerSocket(PORT); mExecutorService = Executors.newCachedThreadPool(); //create a thread pool System.out.println("伺服器已啟動..."); Socket client = null; while(true) { client = server.accept(); //把客戶端放入客戶端集合中
mList.add(client); mExecutorService.execute(new Service(client)); //start a new thread to handle the connection } }catch (Exception e) { e.printStackTrace(); } } static class Service implements Runnable { private Socket socket; private BufferedReader in = null; private String msg = ""; public Service(Socket socket) { this.socket = socket; try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //客戶端只要一連到伺服器,便向客戶端傳送下面的資訊。 } catch (IOException e) { e.printStackTrace(); } } public byte[] readStream(InputStream inStream) throws Exception { ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = -1; while ((len = inStream.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } outSteam.close(); inStream.close(); return outSteam.toByteArray(); } @Override public void run() { try { while(true) { if((msg = in.readLine())!= null) { System.out.println("接收:"+msg); ChatBean bean = new Gson().fromJson(msg, ChatBean.class); //當客戶端傳送的資訊為:exit時,關閉連線 if(bean.content.equals("exit")) { System.out.println("使用者:"+bean.name+"已退出談論組"); mList.remove(socket); in.close(); socket.close(); this.sendmsg(); break; //接收客戶端發過來的資訊msg,然後傳送給客戶端。 } else { this.sendmsg(); } } } } catch (Exception e) { e.printStackTrace(); } } /** * 迴圈遍歷客戶端集合,給每個客戶端都發送資訊。 * 可以使用觀察者模式設計討論組 */ public void sendmsg() { System.out.println(msg); int num =mList.size(); for (int index = 0; index < num; index ++) { Socket mSocket = mList.get(index); PrintWriter pout = null; try { pout = new PrintWriter(new BufferedWriter( new OutputStreamWriter(mSocket.getOutputStream())),true); pout.println(msg); }catch (IOException e) { e.printStackTrace(); } } } } }

Android 部分程式碼如下:

public interface ChatView {

    public String getHost();
    public String getProt();
    public String getUserId();
    public void showDiaolg(String msg);
    public void receiveMsg(ChatBean bean);
}

public class SocketThread extends Thread {

    private Socket socket = null;
    private BufferedReader in = null;
    private PrintWriter out = null;

    private ChatView chatView;

    public SocketThread(ChatView chatView) {
        this.chatView = chatView;
    }

    private void init() {
        try {
            socket = new Socket(chatView.getHost(), Integer.parseInt(chatView.getProt()));
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
            if (!socket.isOutputShutdown()) {
                ChatBean bean = new ChatBean("join", chatView.getUserId());
                out.println(new Gson().toJson(bean));
            }
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
            mHandler.sendEmptyMessage(-1);
        } catch (IOException ex) {
            ex.printStackTrace();
            mHandler.sendEmptyMessage(0);
        } catch (IllegalArgumentException e2) {
            e2.printStackTrace();
            mHandler.sendEmptyMessage(-2);
        }
    }

    public void sendMsg(String msg) {
        ChatBean bean = new ChatBean(msg, chatView.getUserId());
        if (!TextUtils.isEmpty(msg) && socket != null && socket.isConnected()) {
            if (!socket.isOutputShutdown()) {
                out.println(new Gson().toJson(bean));
            }
        }
    }

    //接收執行緒傳送過來資訊,並用TextView顯示
    public Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case -2:
                    chatView.showDiaolg("IllegalArgumentException");
                    break;
                case -1:
                    chatView.showDiaolg("UnknownHostException");
                    break;
                case 0:
                    chatView.showDiaolg("IOException");
                    break;
                case 1:
                    String content = (String) msg.obj;
                    ChatBean bean = new Gson().fromJson(content, ChatBean.class);
                    chatView.receiveMsg(bean);
                    break;
            }
        }
    };

    @Override
    public void run() {
        super.run();
        init();
        //接收伺服器的資訊
        try {
            while (true) {
                if (!socket.isClosed()) {
                    if (socket.isConnected()) {
                        if (!socket.isInputShutdown()) {
                            String content;
                            if ((content = in.readLine()) != null) {
                                content += "\n";
                                Message message = mHandler.obtainMessage();
                                message.obj = content;
                                message.what = 1;
                                mHandler.sendMessage(message);
                            } else {

                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}