android開發之網路學習-Socket學習

say_from_wen發表於2017-12-07

寫在開頭

依然那句話,android需要學的東西太多了。網路知識必不可少也。一點一點總結學習。

相關連結:

android開發之網路學習-TCP/IP

android開發之網路學習-http/https

歡迎大家的補充,共同學習與進步。

Socket概念

Socket(套接字)用於描述IP地址和埠,是通訊鏈的控制程式碼,應用程式可以通過Socket向網路發出請求或者應答網路請求。

Socket是支援TCP/IP協議的網路通訊的基本操作單元,是對網路通訊過程中端點的抽象表示,包含了進行網路通訊所必需的5種資訊:連線所使用的協議、本地主機的IP地址、本地程式的協議埠、遠地主機的IP地址以及遠地程式的協議埠。

Socket的傳輸模式

Socket有兩種主要的操作方式:面向連線(TCP)的和無連線(UDP)的。(對於這方面,可看下上面推薦的文章)。

TCP層則提供面向應用的可靠(tcp)的或非可靠(UDP)的資料傳輸機制,這是網路程式設計的主要物件,一般不需要關心IP層是如何處理資料的。

目前較為流行的網路程式設計模型是客戶機/伺服器(C/S)結構。即通訊雙方一方作為伺服器等待客戶提出請求並予以響應。客戶則在需要服務時向伺服器提 出申請。伺服器一般作為守護程式始終執行,監聽網路埠,一旦有客戶請求,就會啟動一個服務程式來響應該客戶,同時自己繼續監聽服務埠,使後來的客戶也能及時得到服務。

TCP是Tranfer Control Protocol的 簡稱,是一種面向連線的保證可靠傳輸的協議。通過TCP協議傳輸,得到的是一個順序的無差錯的資料流。傳送方和接收方的成對的兩個socket之間必須建 立連線,以便在TCP協議的基礎上進行通訊,當一個socket(通常都是server socket)等待建立連線時,另一個socket可以要求進行連線,一旦這兩個socket連線起來,它們就可以進行雙向資料傳輸,雙方都可以進行傳送或接收操作。TCP在網路通訊上有極強的生命力,例如遠端連線(Telnet)和檔案傳輸(FTP)都需要不定長度的資料被可靠地傳輸。但是可靠的傳輸是要付出代價的,對資料內容正確性的檢驗必然佔用計算機的處理時間和網路的頻寬,因此TCP傳輸的效率不如UDP高。

UDP是User Datagram Protocol的簡稱,是一種無連線的協議,每個資料包都是一個獨立的資訊,包括完整的源地址或目的地址,它在網路上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。UDP操作簡單,而且僅需要較少的監護,因此通常用於區域網高可靠性的分散系統中client/server應用程式。例如視訊會議系統,並不要求音訊視訊資料絕對的正確,只要保證連貫性就可以了,這種情況下顯然使用UDP會更合理一些。

知識點對比: UDP: 1,每個資料包中都給出了完整的地址資訊,因此無需要建立傳送方和接收方的連線。 2,UDP傳輸資料時是有大小限制的,每個被傳輸的資料包必須限定在64KB之內。 3,UDP是一個不可靠的協議,傳送方所傳送的資料包並不一定以相同的次序到達接收方

TCP: 1,面向連線的協議,在socket之間進行資料傳輸之前必然要建立連線,所以在TCP中需要連線時間。 2,TCP傳輸資料大小限制,一旦連線建立起來,雙方的socket就可以按統一的格式傳輸大的資料。 3,TCP是一個可靠的協議,它確保接收方完全正確地獲取傳送方所傳送的全部資料。

Socket的使用(以TCP為例)(先說句,網路許可權要開啟)

客戶端和伺服器端的輸入輸出流的問題(圖解,網上一張圖,挺好。)

這裡寫圖片描述

Socket提供了方法getInputStream()和getOutPutStream()來獲得對應的輸入流和輸出流,以便對Socket進行讀寫操作,這兩個方法的返回值分別是InputStream和OutPutStream物件。

步驟詳解

伺服器端的步驟:

1,指定埠例項化一個ServerSocket 2,呼叫ServerSocket的accept方法等待連線期間阻塞 3,獲取位於底層的Socket流進行讀寫操作 4,將資料封裝成流 5,對Socket進行讀寫 6,關閉流

客戶端的步驟:

1,通過IP地址和埠例項化Socket,請求連線伺服器 2,獲取位於底層的Socket流進行讀寫操作 3,將資料封裝成流(BufferedReader/PrintWriter,DataOutputStream/DataInputStream)的例項 4,對Socket進行讀寫 5,關閉流

Socket的構造方法

Java在包java.net中提供了兩個類Socket和ServerSocket,分別用來表示雙向連線的Socket客戶端和伺服器端。

Socket的構造方法如下:

(1)Socket(InetAddress address, int port); (2)Socket(InetAddress address, int port, boolean stream); (3)Socket(String host, int port); (4)Socket(String host, int port, boolean stream); (5)Socket(SocketImpl impl); (6)Socket(String host, int port, InetAddress localAddr, int localPort); (7)Socket(InetAddress address, int port, InetAddrss localAddr, int localPort);

ServerSocket的構造方法如下:

(1)ServerSocket(int port); (2)ServerSocket(int port, int backlog); (3)ServerSocket(int port, int backlog, InetAddress bindAddr);

其中,引數address、host和port分別是雙向連線中另一方的IP地址、主機名和埠號;引數stream表示Socket是流Socket還是資料包Socket;引數localAddr和localPort表示本地主機的IP地址和埠號;SocketImpl是Socket的父類,既可以用來建立ServerSocket,也可以用來建立Socket。

注意,在選擇埠時,必須小心。每一個埠提供一種特定的服務,只有給出正確的埠,才 能獲得相應的服務。0~1023的埠號為系統所保留,例如http服務的埠號為80,telnet服務的埠號為21,ftp服務的埠號為23, 所以我們在選擇埠號時,最好選擇一個大於1023的數以防止發生衝突。 在建立socket時如果發生錯誤,將產生IOException,在程式中必須對之作出處理。所以在建立Socket或ServerSocket是必須捕獲或丟擲例外。

簡單程式碼實現

伺服器端:(建議用MyEclipse寫個簡單的java檔案)

public class ServerSocketDemo{  
  
    public static void main(String[] args) {  
        new ServerThread().start();  
    }  
}  
  
// 建立一個執行緒在後臺監聽(例子就是用一個死迴圈,實際否。)  
class ServerThread extends Thread { 
 
    private static int Port = 52000;  
    ServerSocket serversocket = null;  
  
    public void run() {  
    
        try {  
            // 建立一個serversocket物件,並讓他在Port埠監聽  
            serversocket = new ServerSocket(Port);  
            while (true) {  
                // 呼叫serversocket的accept()方法,接收客戶端傳送的請求  
                Socket socket = serversocket.accept();  
                BufferedReader buffer = new BufferedReader(  
                        new InputStreamReader(socket.getInputStream()));  
                // 讀取資料  
                String msg = buffer.readLine();  
                System.out.println("msg:" + msg);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                serversocket.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  
複製程式碼

android的客戶端:

public class Client extends Activity {  
    private static String IpAddress = "192.168.1.12";  
    private static int Port = 52000;  
    private EditText edittext = null;  
    private Button send = null;  
    Socket socket = null;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        edittext = (EditText) findViewById(R.id.edittext);  
        send = (Button) findViewById(R.id.send);  
        send.setOnClickListener(new OnClickListener() {  
  
            @Override  
            public void onClick(View v) {  
                sendMsg();  
            }  
        });  
    }  
  
    // 傳送資訊  
    public void sendMsg() {  
  
        try {  
            // 建立socket物件,指定伺服器端地址和埠號  
            socket = new Socket(IpAddress, Port);  
            // 獲取 Client 端的輸出流  
            PrintWriter out = new PrintWriter(new BufferedWriter(  
                    new OutputStreamWriter(socket.getOutputStream())), true);  
            // 填充資訊  
            out.println(edittext.getText());  
            System.out.println("msg=" + edittext.getText());  
            // 關閉 
            out.close();
  
        } catch (UnknownHostException e1) {  
            e1.printStackTrace();  
        } catch (IOException e1) {  
            e1.printStackTrace();  
        } finally {  
            try {  
                socket.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  
複製程式碼

總結

寫這麼多隻是想擴充下socket程式設計的認知,實際開發中我們一般是不會自己寫socket的,對於我們android端的即時通訊功能,一般會採用三方的解決方案,環信,融雲都是很好的選擇,如果需求必須用到socket的話,有很多框架也可以選擇。

https://github.com/vilyever/AndroidSocketClient (國庫,註釋都是中文哦)

github.com/typ0520/biz…(支援RxJava,沒用,你可以試一下給點反饋嘿嘿)

寫在最後

試了下,確實是能收到訊息的,不過我只是簡單的學習了下。在這裡感謝以下大神的部落格。

www.jianshu.com/p/089fb79e3…

http://blog.csdn.net/liuyi1207164339/article/details/50960477

http://blog.csdn.net/x605940745/article/details/17001641

https://www.cnblogs.com/menlsh/archive/2013/06/12/3133296.html

相關文章