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

寫在開頭

依然那句話,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(國庫,註釋都是中文哦)
https://github.com/typ0520/bizsocket(支持RxJava,沒用,你可以試一下給點反饋嘿嘿)

寫在最後

試了下,確實是能收到消息的,不過我只是簡單的學習了下。在這裏感謝以下大神的博客。

http://www.jianshu.com/p/089fb79e308b
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章