Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android入門筆記 - 網絡通信 - Socket

Android入門筆記 - 網絡通信 - Socket

編輯:關於Android編程

今天來學習一下android中通信方式中的socket。上兩次我們分別使用了HttpURLConnection , 和 HttpClient來實現通信,他們都是在使用HTTP協議,Socket被稱為套接字,使用的協議有TCP和UDP,TCP和UDP的區別在於TCP是可靠穩定的,自帶容錯處理等優點,所以效率要低一點。然後UDP就不那麼穩定了,當使用UDP發送數據的時候,每次send,那麼socket只管send,不會管send之後對方是否收到,是否順序正確,所以UDP被稱為不穩定的傳輸,但是其效率卻很高,因為做的事情很簡單。

今天我們學習socket是使用tcp協議,在android中使用socket其實就是使用java中的socket,看應用的包 java.net.*; 就知道。

 

我們來完成一個小的局域網聊天的程序,包含一個服務器,android應用作為客戶端,一台手機發送信息後,服務器會轉發給其他手機,很簡單。代碼比較多,後面附上下載地址,我們先來看怎麼使用socket。

 

客戶端:

客戶端Socket使用步驟:

(1)Socket mSocket = new Socket( SERVER_IP, SERVER_PORT); // 兩個參數分別為服務器ip地址,和服務器監聽的端口號

(2)BufferedReader mBufferReader = new BufferedReader(new InputStreamReader( mSocket.getInputStream())); // 通過socket.getInputStream() 可以得到輸入流,可從socket獲取服務器發送的數據。為了能一行一行讀取,我們將其轉化為 BufferReader,可以使用BufferReader.readLine() 一行一行得去取等待在socket上的數據。

(3)PrintWriter mPrintWriter = new PrintWriter(mSocket.getOutputStream(), true); // 通過socket.getOutputStream() 可以得到輸入流,就可以通過socket向服務器發送數據, 這裡需要套上 PrintWriter 標准的接口,就可以使用 mPrintWriter.println(“ ... ),直接發送數據。

(4)使用完後斷開連接。

我們來看一看實例:

 

mSocket = new Socket(SERVER_IP, SERVER_POART);
mBufferReader = new BufferedReader(new InputStreamReader(
	mSocket.getInputStream()));
mPrintWriter = new PrintWriter(mSocket.getOutputStream(), true);
如果沒有報 Exception那就表示鏈接服務器已經成功,這時就可以使用 mBufferReader和 mPrintWrinter 來實現數據的收發。

 

讀取數據:

 

                while (true) {
                    if (null != (mStrMsg = mBufferReader.readLine())) {
                        mStrMsg += 
;
                        if(mStrMsg.trim().equals(exit)){
                            mHandler.sendMessage(mHandler.obtainMessage(2));
                            return ;
                        }
                        mHandler.sendMessage(mHandler.obtainMessage(0));
                    }
                }
發送數據:

 

 

    private View.OnClickListener sendListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String str = mEtMessage.getText().toString().trim();
            if(mPrintWriter == null){
                showToast(請先連接服務器!);
                return ;
            }
            mPrintWriter.println(str);
            mPrintWriter.flush();
            mEtMessage.setText();
        }
    };
斷開連接:

 

 

showToast(斷開連接);
    try {
	mBufferReader.close();
	mPrintWriter.close();
	mSocket.close();
	mSocket = null;
	if (mGetMessageThread != null) {
	    mGetMessageThread = null;
	}
     } catch (IOException e) {
          e.printStackTrace();
     }

 

服務端:

在服務端我們需要有一個ServerSocket,這是用來接收連接請求的,當每接收到一個一個請求後就會返回一個Socket套接字,就可以使用這個套接字與客戶端通信。注意:服務器端應該是一直運行,且可以接收很多連接的程序,服務器程序一定不能被關閉或者崩掉,所以在設計服務器的時候要考慮很多很多事情,我們這裡只是簡單的處理收到客戶端請求連接,然後將其加入到list當中,如果收到消息,就將收到的消息轉發給列表中其他所有socket,很簡單的處理。

使用步驟:

(1)ServerSocket mServerSocket = new ServerSocket(SERVERPORT); // 創建監聽連接ServerSocket

(2)不停監聽 mServerSocket, 使用accept() 接收連接,如果偵測到連接,就啟動一個線程,將返回值socket傳入,那麼每個線程就對應一個客戶端,可以與客戶端通信了。

(3)接下來就是 每個線程如果收到數據,就需要將消息轉發給 客戶單列表中所有其他用戶。

(4)客戶端斷開鏈接後,清除客戶socket信息。

啟動監聽連接,並啟動一個線程池,當監聽到連接請求時創建啟動線程,並放入到線程池中運行:

        try {
            mServerSocket = new ServerSocket(SERVERPORT);
            mExecutorService = Executors.newCachedThreadPool();
            System.out.println(Server Start...);
            Socket client = null;
            while (true) {
                client = mServerSocket.accept();
                mClientList.add(client);
                mExecutorService.execute(new ThreadServer(client));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
線程中接收消息,以及轉發消息:

 

 

    private class ThreadServer implements Runnable {
        private Socket mClient;
        private BufferedReader mBufferedReader;
        private PrintWriter mPrintWriter;
        private String mStrMsg;

        public ThreadServer(Socket client) throws IOException {
            this.mClient = client;
            mBufferedReader = new BufferedReader(new InputStreamReader(
                    mClient.getInputStream()));
            mStrMsg = usr: + this.mClient.getInetAddress() +  connected
                    + ,total: + mClientList.size();
            sendMessage(mStrMsg);
        }

        private void sendMessage(String msg) throws IOException {
            System.out.println(msg);
            for (Socket client : mClientList) {
                mPrintWriter = new PrintWriter(client.getOutputStream(), true);
                mPrintWriter.println(msg);
            }
        }

        @Override
        public void run() {
            try {
                while (null != (mStrMsg = mBufferedReader.readLine())) {
                    if (mStrMsg.trim().equals(exit)) {
                        mStrMsg = user: + mClient.getInetAddress() +  exit!
                                + total: + (mClientList.size() - 1);
                        sendMessage(mStrMsg);

                        mPrintWriter = new PrintWriter(
                                mClient.getOutputStream(), true);
                        mPrintWriter.println(exit);

                        mBufferedReader.close();
                        mPrintWriter.close();
                        mClientList.remove(mClient);
                        mClient.close();
                        break;
                    } else {
                        mStrMsg = mClient.getInetAddress() + : + mStrMsg;
                        sendMessage(mStrMsg);
                    }
                }
            } catch (SocketException e) {
                // e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

 

 

如果沒有網絡基礎,這個理解起來還是有點復雜的,下面貼了項目代碼,大家自己去體會一下吧,使用socket其實很簡單,主要是邏輯處理。

這裡有幾點需要注意的:

(1)android2.3之後不能再UI主線程中調用網絡請求,會直接崩潰,所以需要使用handler來發送消息處理

(2)實例代碼放在你的機子上不一定能使用,SERVER_IP為計算機在局域網的本機地址,需要自己修改。 android客戶端需要連上計算機,這樣客戶端就能找到服務器了。

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved