Android TCP socket通信

轉載請註明出處:http://blog.csdn.net/vnanyesheshou/article/details/74896575

之前做過的一個局域網內TCP通信、聊天的demo(當然不是局域網也可以進行通信,剛試了一下可以的),週日整理了一下。該demo可以做客戶端,也可以做服務端。兩個手機都安裝該應用,一個做客戶端、一個做服務端,然後進行通信(連接在同一局域網,或服務器是外網ip,客戶端可以上網)。
20180728修改:Android7.0以上socket發送數據失敗,需要將發送的操作放到子線程中,最新demo以更新。

demo下載地址http://www.demodashi.com/demo/10567.html


1 簡介

TCP(Transmission Control Protocol):傳輸控制協議,是一種面向連接的、可靠的、基於字節流的傳輸層通信協議。

在Internet協議族(Internet protocol suite)中,TCP層是位於IP層之上,應用層之下的中間層。不同主機的應用層之間經常需要可靠的、像管道一樣的連接,但是IP層不提供這樣的流機制,而是提供不可靠的包交換。

Socket 英文原義是“孔”或“插座”。通常稱爲”套接字”,用於描述IP地址和端口,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不同的端口對應於不同的服務(客戶若是需要哪種服務,就講插頭連到相應的插座上),客戶的“插頭”也是一個socket。
Socket通信,需要服務端和客戶端,兩端都要實例化一個Socket。但服務器和客戶端的Socket是不一樣的。

  • 客戶端:可以連接服務端、發送數據、接收數據、關閉連接等。
  • 服務端:可以實現綁定綁定端口,接收客戶端的連接、接收數據,發送數據等。

Android在包java.net包下提供了ServerSocketSocket類,ServerSocket用於創建服務器的Socket。Socket用於實例化客戶端的Socket。當連接成功,客戶端和服務端都會產生一個Socket實例,通過此Socket進行通信。
先看下效果圖:
這裏寫圖片描述
這裏寫圖片描述 這裏寫圖片描述


2 服務端

服務端ServerSocket的構造方法有以下幾種:

  • ServerSocket ():構造一個新的未綁定的ServerSocket。
  • ServerSocket (int port):構造一個新的ServerSocket並綁定到指定端口,如果port等於0,則端口由系統自動分配。
  • ServerSocket (int port, int backlog):構造一個新的ServerSocket並綁定到指定端口,並指定進入隊列的數目。如果port等於0,則端口由系統自動分配。
  • ServerSocket (int port, int backlog, InetAddress localAddress):構造一個新的ServerSocket並綁定到指定端口和指定的地址,並指定進入隊列的數目。如果port等於0,則端口由系統自動分配。如果localAddress爲null,則可以使用任意地址。
  • -

TCP服務端工作具體步驟:
步驟1:創建一個ServerSocket,並綁定到指定端口上。

try {
    //開啓服務、指定端口號
    ServerSocket mServerSocket = new ServerSocket(5566);
} catch (IOException e) {
    e.printStackTrace();
    Toast.makeText(this, "服務開啓失敗", Toast.LENGTH_SHORT).show();
    return;
}

步驟2:調用ServerSocket的accept(),監聽連接請求,如果客戶端請求連接,則接收連接,返回Scoekt對象。

Socket mSocket = mServerSocket.accept();
步驟3:調用Socket類的getInputStream()和getOutputStream()獲取輸入輸出流。

class SocketAcceptThread extends Thread{
    @Override
    public void run() {
        try {
            //等待客戶端的連接,Accept會阻塞,直到建立連接,
            //所以需要放在子線程中運行。
            mSocket = mServerSocket.accept();
            //獲取輸入流
            mInStream = mSocket.getInputStream();
            //獲取輸出流
            mOutStream = mSocket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
            mHandler.sendEmptyMessage(MSG_SOCKET_ACCEPTFAIL);
            return;
        }
        Log.i(TAG, "accept success");
        mHandler.sendEmptyMessage(MSG_SOCKET_CONNECT);
    }
}

步驟4:開始發送、接收數據。
發送數據:

private void writeMsg(String msg){
    if(msg.length() == 0 || mOutStream == null)
        return;
    try {   //發送
        mOutStream.write(msg.getBytes());
        mOutStream.flush();
    }catch (Exception e) {
        e.printStackTrace();
    }
}

接收數據:(從輸入流讀取數據,需要在一個子線程中循環運行下面的方法。)

byte[] buffer = new byte[1024];
//循環執行read,用來接收數據。
//數據存在buffer中,count爲讀取到的數據長度。
int count = mInStream.read(buffer);

步驟5:服務不再需要,則關閉服務。

if(mServerSocket != null){
    try {
        mServerSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3 客戶端

TCP客戶端工作具體步驟:
步驟1:創建一個Socket,連接到服務器端、指定端口號。放在子線程中運行,否則會有問題。

class SocketConnectThread extends Thread{
    public void run(){
        try {
            //指定ip地址和端口號
            mSocket = new Socket(mIpAddress,mClientPort);
            if(mSocket != null){
                //獲取輸出流、輸入流
                mOutStream = mSocket.getOutputStream();
                mInStream = mSocket.getInputStream();
            }
        } catch (Exception e) {
            e.printStackTrace();
            mHandler.sendEmptyMessage(MSG_SOCKET_CONNECTFAIL);
            return;
        }
        Log.i(TAG,"connect success");
        mHandler.sendEmptyMessage(MSG_SOCKET_CONNECT);
    }

}

步驟2:調用Socket類的getInputStream()和getOutputStream()獲取輸入輸出流。
具體代碼如上所示。
步驟3:發送、接收數據。(發送接收數據與服務端方法相同。)
發送數據:

private void writeMsg(String msg){
    if(msg.length() == 0 || mOutStream == null)
        return;
    try {   //發送
        mOutStream.write(msg.getBytes());
        mOutStream.flush();
    }catch (Exception e) {
        e.printStackTrace();
    }
}

接收數據:(從輸入流讀取數據,需要在一個子線程中循環運行下面的方法。)

byte[] buffer = new byte[1024];
//循環執行read,用來接收數據。
//數據存在buffer中,count爲讀取到的數據長度。
int count = mInStream.read(buffer);

步驟4:關閉Socket

public void closeConnection(){
    try {
        if (mOutStream != null) {
            mOutStream.close(); //關閉輸出流
            mOutStream = null;
        }
        if (mInStream != null) {
            mInStream.close(); //關閉輸入流
            mInStream = null;
           }
        if(mSocket != null){
            mSocket.close();  //關閉socket
            mSocket = null;
        }
       } catch (IOException e) {
           e.printStackTrace();
       }
    if(mReceiveThread != null){
        mReceiveThread.threadExit();
        mReceiveThread = null;
    }
   }

4 總結

在清單文件中添加權限

<uses-permission android:name="android.permission.INTERNET"/>

TCP通信的使用基本就完成了,最後看一下圖片,更容易理解其通信機制。
這裏寫圖片描述

發佈了129 篇原創文章 · 獲贊 270 · 訪問量 97萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章