Android如何實現TCP和UDP傳輸

投稿發表於2015-03-16

TCP和UDP在網路傳輸中非常重要,在Android開發中同樣重要。

首先我們來看一下什麼是TCP和UDP。

什麼是TCP?

TCP:Transmission Control Protocol 傳輸控制協議TCP是一種面向連線(連線導向)的、可靠的、基於位元組流的運輸層(Transport layer)通訊協議,由IETF的RFC 793說明(specified)。在簡化的計算機網路OSI模型中,它完成第四層傳輸層所指定的功能。應用層向TCP層傳送用於網間傳輸的、用8位位元組表示的資料流,然後TCP把資料流分割成適當長度的報文段(通常受該計算機連線的網路的資料鏈路層的最大傳送單元(MTU)的限制)。之後TCP把結果包傳給IP層,由它來通過網路將包傳送給接收端實體的TCP層。TCP為了保證不發生丟包,就給每個位元組一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。然後接收端實體對已成功收到的位元組發回一個相應的確認(ACK);如果傳送端實體在合理的往返時延(RTT)內未收到確認,那麼對應的資料(假設丟失了)將會被重傳。TCP用一個校驗和函式來檢驗資料是否有錯誤;在傳送和接收時都要計算校驗和。

首先,TCP建立連線之後,通訊雙方都同時可以進行資料的傳輸,其次,他是全雙工的;在保證可靠性上,採用超時重傳和捎帶確認機制。

在流量控制上,採用滑動視窗協議[1],協議中規定,對於視窗內未經確認的分組需要重傳。

在擁塞控制上,採用慢啟動演算法。

什麼是UDP?

UDP 是User Datagram Protocol的簡稱, 中文名是使用者資料包協議,是 OSI 參考模型中一種無連線的傳輸層協議,提供面向事務的簡單不可靠資訊傳送服務。它是IETF RFC 768是UDP的正式規範。在網路中它與TCP協議一樣用於處理資料包。在OSI模型中,在第四層——傳輸層,處於IP協議的上一層。UDP有不提供資料包分組、組裝和不能對資料包的排序的缺點,也就是說,當報文傳送之後,是無法得知其是否安全完整到達的。 UDP用來支援那些需要在計算機之間傳輸資料的網路應用。包括網路視訊會議系統在內的眾多的客戶/伺服器模式的網路應用都需要使用UDP協議。UDP協議從問世至今已經被使用了很多年,雖然其最初的光彩已經被一些類似協議所掩蓋,但是即使是在今天,UDP仍然不失為一項非常實用和可行的網路傳輸層協議。

與所熟知的TCP(傳輸控制協議)協議一樣,UDP協議直接位於IP(網際協議)協議的頂層。根據OSI(開放系統互連)參考模型,UDP和TCP都屬於傳輸層協議。

UDP協議的主要作用是將網路資料流量壓縮成資料包的形式。一個典型的資料包就是一個二進位制資料的傳輸單位。每一個資料包的前8個位元組用來包含報頭資訊,剩餘位元組則用來包含具體的傳輸資料。

TCP和UDP在android中的使用和在Java裡是完全一樣的。

首先我們看看TCP連線,下圖為TCP連線的一個示意圖:

TCP原理TCP傳輸原理

是不是很好理解,這裡就不多說了,直接看程式碼吧!實踐出真知。

TCP伺服器端程式碼:

try {  
            Boolean endFlag = false;  
            ServerSocket ss = new ServerSocket(12345);  
            while (!endFlag) {  
                // 等待客戶端連線  
                Socket s = ss.accept();  
                BufferedReader input = new BufferedReader(newInputStreamReader(s.getInputStream()));  
                //注意第二個引數據為true將會自動flush,否則需要需要手動操作output.flush()  
                PrintWriter output = newPrintWriter(s.getOutputStream(),true);  
                String message = input.readLine();  
                Log.d("Tcp Demo", "message from Client:"+message);  
                output.println("message received!");  
                //output.flush();  
                if("shutDown".equals(message)){  
                    endFlag=true;  
                }  
                s.close();  
            }  
            ss.close();  

        } catch (UnknownHostException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }

TCP客戶端程式碼:

try {  
            Socket s = new Socket("localhost", 12345);  
            // outgoing stream redirect to socket  
            OutputStream out = s.getOutputStream();  
            // 注意第二個引數據為true將會自動flush,否則需要需要手動操作out.flush()  
            PrintWriter output = new PrintWriter(out, true);  
            output.println("Hello IdeasAndroid!");  
            BufferedReader input = new BufferedReader(newInputStreamReader(s  
                    .getInputStream()));  
            // read line(s)  
            String message = input.readLine();  
            Log.d("Tcp Demo", "message From Server:" + message);  
            s.close();  

        } catch (UnknownHostException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }

下面我們看看UDP:

UDP傳輸遠離UDP傳輸原理

UDP伺服器端程式碼:

// UDP伺服器監聽的埠  
        Integer port = 12345;  
        // 接收的位元組大小,客戶端傳送的資料不能超過這個大小  
        byte[] message = new byte[1024];  
        try {  
            // 建立Socket連線  
            DatagramSocket datagramSocket = new DatagramSocket(port);  
            DatagramPacket datagramPacket = new DatagramPacket(message,  
                    message.length);  
            try {  
                while (true) {  
                    // 準備接收資料  
                    datagramSocket.receive(datagramPacket);  
                    Log.d("UDP Demo", datagramPacket.getAddress()  
                            .getHostAddress().toString()  
                            + ":" + new String(datagramPacket.getData()));  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        } catch (SocketException e) {  
            e.printStackTrace();  
        }

UDP客戶端程式碼:

public static void send(String message) {  
        message = (message == null ? "Hello IdeasAndroid!" : message);  
        int server_port = 12345;  
        DatagramSocket s = null;  
        try {  
            s = new DatagramSocket();  
        } catch (SocketException e) {  
            e.printStackTrace();  
        }  
        InetAddress local = null;  
        try {  
            // 換成伺服器端IP  
            local = InetAddress.getByName("localhost");  
        } catch (UnknownHostException e) {  
            e.printStackTrace();  
        }  
        int msg_length = message.length();  
        byte[] messagemessageByte = message.getBytes();  
        DatagramPacket p = new DatagramPacket(messageByte, msg_length, local,  
                server_port);  
        try {  
            s.send(p);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }

程式碼中需要注意的地方已做了註釋,希望本文對您有所幫助!

相關文章