Android網(wǎng)絡(luò)編程之--Socket編程

大家好,我是徐愛卿。博客地址:flutterall.com

引言

Android網(wǎng)絡(luò)編程一直都是我想記錄的一篇文章,由于種種原因,一直推遲,終于在在今天開始寫了。這是一個(gè)好的開始,O(∩_∩)O哈哈~。
網(wǎng)絡(luò)上有很多關(guān)于Android網(wǎng)絡(luò)編程的文章,我感覺沒有一個(gè)適當(dāng)?shù)目偨Y(jié)合適我的。所以,今天我決定將Android網(wǎng)絡(luò)編程的系列文章做一個(gè)總結(jié),在這里與大家分享。
這幾篇系列文章總的分為兩大模塊:Socket編程與HTTP編程(關(guān)于在Android中的)。今天我們先來看看通過Socket編程實(shí)現(xiàn)的服務(wù)器與客戶端(我們這里是手機(jī)端)之間的通信。

這篇文章你能學(xué)到什么?

  • 了解網(wǎng)絡(luò)通信的基本原理
  • 學(xué)會(huì)最基礎(chǔ)的Socket通信原理(萬丈高樓平地起)
  • 明白TCP協(xié)議與UDP協(xié)議的區(qū)別與適用場(chǎng)景

網(wǎng)絡(luò)編程基礎(chǔ)

TCP/IP協(xié)議

我們先看看從宏觀上來看兩臺(tái)機(jī)器是如何通信的。
我們通過QQ和服務(wù)器進(jìn)行通信,都需要哪些東西呢?
兩臺(tái)主機(jī)進(jìn)行通信,需要知道雙方電腦的的地址(也就是IP地址);知道兩個(gè)電腦的地址之后,我們還需要知道我發(fā)送到目的電腦的目的軟件(使用端口標(biāo)記)。這樣兩臺(tái)電腦連接成功之后就可以進(jìn)行通信了。
那么這些東西例如:目的地如何規(guī)定,發(fā)送的數(shù)據(jù)如何包裝,放到哪里?這中間就需要有各種協(xié)議。大家都使用這個(gè)協(xié)議,統(tǒng)一成一個(gè)規(guī)范,這樣符合這個(gè)規(guī)范的各種設(shè)備之間能夠進(jìn)行兼容性的通信。
最為廣泛的的協(xié)議就是OSI協(xié)議和TCP/IP協(xié)議了,但是OSI協(xié)議較為繁瑣,未推廣(想了解的自己Google)。反而TCP/IP(transfer control protocol/internet protocol,傳輸控制協(xié)議/網(wǎng)際協(xié)議)協(xié)議簡(jiǎn)單明了,得到現(xiàn)今的廣泛使用。
TCP/IP準(zhǔn)確的說是一組協(xié)議,是很多協(xié)議的集合,是一組協(xié)議集合的簡(jiǎn)稱。來看看:

名稱 協(xié)議 功能
應(yīng)用層 HTTP、Telnet、FTP、TFTP 提供應(yīng)用程序網(wǎng)絡(luò)接口
傳輸層 TCP、UDP 建立端到端的連接
網(wǎng)絡(luò)層 IP 尋址和路由
數(shù)據(jù)鏈路層 Ethernet、802.3、PPP 物理介質(zhì)訪問
物理層 接口和電纜 二進(jìn)制數(shù)據(jù)流傳輸

下面以QQ的數(shù)據(jù)傳輸為例子:

QQ的數(shù)據(jù)傳輸

IP地址、端口

在上節(jié)中我們知道端到端的連接提到了幾個(gè)關(guān)鍵的字眼:IP地址、端口;
IP地址用來標(biāo)記唯一的計(jì)算機(jī)位置,端口號(hào)用來標(biāo)記一臺(tái)電腦中的不同應(yīng)用程序。
其中IP地址是32為二進(jìn)制,例如:192.168.0.0.1等等,這個(gè)組合方式是一種協(xié)議拼起來的,詳情Google。
端口號(hào)范圍是065536,其中01023是系統(tǒng)專用,例如:

協(xié)議名稱 協(xié)議功能 默認(rèn)端口號(hào)
HTTP(HypertextTransfer Protocol)超文本傳輸協(xié)議 瀏覽網(wǎng)頁(yè) 80
FTP(File TransferProtocol) 文件傳輸協(xié)議 用于網(wǎng)絡(luò)上傳輸文件 21
TELNET 遠(yuǎn)程終端訪問 23
POP3(Post OfficeProtocol) 郵局協(xié)議版本 110

IP地址和端口號(hào)組成了我們的Socket,也就是“套接字”,Socket只是一個(gè)API。
Socket原理機(jī)制:
通信的兩端都有Socket
網(wǎng)絡(luò)通信其實(shí)就是Socket間的通信
數(shù)據(jù)在兩個(gè)Socket間通過IO傳輸

單獨(dú)的Socke是沒用任何作用的,基于一定的協(xié)議(比如:TCP、UDP協(xié)議)下的socket編程才能使得數(shù)據(jù)暢通傳輸,下面我們就開始吧。

基于TCP(傳輸控制協(xié)議)協(xié)議的Socket編程

以下將“基于TCP(傳輸控制協(xié)議)協(xié)議的Socket編程”簡(jiǎn)稱為TCP編程

既然基于TCP,那么就有著它的一套代碼邏輯體系。我們只需要在Socket API的幫助下,使用TCP協(xié)議,就可以進(jìn)行一個(gè)完整的TCP編程了。

主要API:
Socket,客戶端相關(guān)

  • 構(gòu)造方法
    public Socket(String host, int port) throws UnknownHostException, IOException
    釋義:創(chuàng)建一個(gè)流套接字并將其連接到指定主機(jī)上的指定端口號(hào)(就是用來連接到host主機(jī)的port端口的)
  • 方法

|方法名稱 | 方法功能|
| ------------- :|-------------:|
|getInputStream()) | 拿到此套接字的輸入流,收到的數(shù)據(jù)就在這里 |
|getOutputStream()| 返回此套接字的輸出流。 要發(fā)送的數(shù)據(jù)放到這里|

ServerSocket,服務(wù)器相關(guān)

  • 構(gòu)造方法
    ServerSocket(int port)
    釋義:創(chuàng)建服務(wù)端的監(jiān)聽port端口的套接字
  • 方法
    Socket accept() throws IOException偵聽并接受到此套接字的連接。此方法在連接傳入之前一直阻塞。服務(wù)端通過這個(gè)方法拿到與客戶端建立端到端的連接的socket。

總體流程圖示:

Socket通信流程
  • TCP編程的服務(wù)端流程:
    1.創(chuàng)建ServerSocket類對(duì)象-serverSocket
    2.使用serverSocket開始一直阻塞監(jiān)聽,等待客戶端發(fā)送來數(shù)據(jù)并且得到socket
    3.根據(jù)socket的輸入流讀取客戶端的數(shù)據(jù),根據(jù)socket的輸出流返回給客戶端數(shù)據(jù)
    4.關(guān)閉socket以及IO流
  • TCP編程的客戶端對(duì)象
    1.創(chuàng)建客戶端的socket對(duì)象
    2.使用客戶端的socket對(duì)象的輸出流發(fā)送給服務(wù)器數(shù)據(jù),使用客戶端的socket對(duì)象的輸入流得到服務(wù)端的數(shù)據(jù)

TCP編程

下面我們使用上面的TCP編程的流程來實(shí)現(xiàn):手機(jī)發(fā)送信息到服務(wù)器,服務(wù)器返回給我們數(shù)據(jù)。

服務(wù)端的話,這里使用eclipse。使用Eclipse新建一個(gè)Server.java來處理服務(wù)器端的邏輯。客戶端的話使用AS來新建一個(gè)Client.java文件。然后運(yùn)行服務(wù)器,在運(yùn)行手機(jī)上的程序,從手機(jī)上發(fā)送一段內(nèi)容到服務(wù)器端接收。大概就是這里流程。

手機(jī)發(fā)送信息到服務(wù)器,服務(wù)器返回給我們數(shù)據(jù)

服務(wù)器端:

服務(wù)器端新建TcpSocketDemo工程

Code:


package com.hui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) {
     
        try {
            // 為了看流程,我就把所有的代碼都放在main函數(shù)里了,也沒有捕捉異常,直接拋出去了。實(shí)際開發(fā)中不可取。
            // 1.新建ServerSocket對(duì)象,創(chuàng)建指定端口的連接
            ServerSocket serverSocket = new ServerSocket(12306);
            System.out.println("服務(wù)端監(jiān)聽開始了~~~~");
            // 2.進(jìn)行監(jiān)聽
            Socket socket = serverSocket.accept();// 開始監(jiān)聽9999端口,并接收到此套接字的連接。
            // 3.拿到輸入流(客戶端發(fā)送的信息就在這里)
            InputStream is = socket.getInputStream();
            // 4.解析數(shù)據(jù)
            InputStreamReader reader = new InputStreamReader(is);
            BufferedReader bufReader = new BufferedReader(reader);
            String s = null;
            StringBuffer sb = new StringBuffer();
            while ((s = bufReader.readLine()) != null) {
                sb.append(s);
            }
            System.out.println("服務(wù)器:" + sb.toString());
            // 關(guān)閉輸入流
            socket.shutdownInput();

            OutputStream os = socket.getOutputStream();
            os.write(("我是服務(wù)端,客戶端發(fā)給我的數(shù)據(jù)就是:"+sb.toString()).getBytes());
            os.flush();
            // 關(guān)閉輸出流
            socket.shutdownOutput();
            os.close();

            // 關(guān)閉IO資源
            bufReader.close();
            reader.close();
            is.close();

            socket.close();// 關(guān)閉socket
            serverSocket.close();// 關(guān)閉ServerSocket

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


注意:
在使用TCP編程的時(shí)候,最后需要釋放資源,關(guān)閉socket(socket.close());關(guān)閉socket輸入輸出流(socket.shutdownInput()以及socket.shutdownOutput());關(guān)閉IO流(is.close() os.close())。需要注意的是:關(guān)閉socket的輸入輸出流需要放在關(guān)閉io流之前。因?yàn)椋?<u>**關(guān)閉IO流會(huì)同時(shí)關(guān)閉socket,一旦關(guān)閉了socket的,就不能再進(jìn)行socket的相關(guān)操作了。而,只關(guān)閉socket輸入輸出流(socket.shutdownInput()以及socket.shutdownOutput())不會(huì)完全關(guān)閉socket,此時(shí)任然可以進(jìn)行socket方面的操作。 **</u>所以要先調(diào)用socket.shutdownXXX,然后再調(diào)用io.close();

客戶端:

頁(yè)面文件沒什么好看的。然后就是點(diǎn)擊button的時(shí)候發(fā)送數(shù)據(jù),收到數(shù)據(jù)展示出來。我們這里主要看點(diǎn)擊按鈕時(shí)做的事情。

public void onClick(View view){
        new Thread(){
            @Override
            public void run() {
                super.run();
                try {
                    //1.創(chuàng)建監(jiān)聽指定服務(wù)器地址以及指定服務(wù)器監(jiān)聽的端口號(hào)
                    Socket socket = new Socket("111.111.11.11", 12306);//111.111.11.11為我這個(gè)本機(jī)的IP地址,端口號(hào)為12306.
                    //2.拿到客戶端的socket對(duì)象的輸出流發(fā)送給服務(wù)器數(shù)據(jù)
                    OutputStream os = socket.getOutputStream();
                    //寫入要發(fā)送給服務(wù)器的數(shù)據(jù)
                    os.write(et.getText().toString().getBytes());
                    os.flush();
                    socket.shutdownOutput();
                    //拿到socket的輸入流,這里存儲(chǔ)的是服務(wù)器返回的數(shù)據(jù)
                    InputStream is = socket.getInputStream();
                    //解析服務(wù)器返回的數(shù)據(jù)
                    InputStreamReader reader = new InputStreamReader(is);
                    BufferedReader bufReader = new BufferedReader(reader);
                    String s = null;
                    final StringBuffer sb = new StringBuffer();
                    while((s = bufReader.readLine()) != null){
                        sb.append(s);
                    }
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv.setText(sb.toString());
                        }
                    });
                    //3、關(guān)閉IO資源(注:實(shí)際開發(fā)中需要放到finally中)
                    bufReader.close();
                    reader.close();
                    is.close();
                    os.close();
                    socket.close();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }

注意!
實(shí)際開發(fā)中的關(guān)閉IO資源需要放到finally中。這里主要是為了先理解TCP編程的socket通信。還有,上面講過的io.close()需要放到socket.showdownXX()后面。
關(guān)于new Socket("111.111.11.11", 12306),如何查看本機(jī)地址,自己百度哦~~~

整體運(yùn)行結(jié)果如下:

TCP的單線程編程

在上圖中,我們手機(jī)端發(fā)送完一個(gè)請(qǐng)求后,服務(wù)端(Server)拿到數(shù)據(jù),解析數(shù)據(jù),返回給客戶端數(shù)據(jù),關(guān)閉所有資源,也就是服務(wù)器關(guān)閉了。這時(shí),如果另一個(gè)客戶端再想跟服務(wù)器進(jìn)行通信時(shí),發(fā)現(xiàn)服務(wù)器已經(jīng)關(guān)閉了,無法與服務(wù)器再次進(jìn)行通信。換句話說,只能跟服務(wù)器通信一次,服務(wù)端 只能支持單線程數(shù)據(jù)處理。也就是說,上面的服務(wù)器的代碼無法實(shí)現(xiàn)多線程編程,只能進(jìn)行一次通信。
那么如果我們想實(shí)現(xiàn)server的多線程數(shù)據(jù)處理,使得server處理完我這個(gè)請(qǐng)求后不會(huì)關(guān)閉,任然可以處理其他客戶端的請(qǐng)求,怎么辦呢?

TCP的多線程編程

思路:
在上面例子中,我們執(zhí)行serversocket.accept()等待客戶端去連接,與客戶建立完連接后,拿到對(duì)應(yīng)的socket,然后進(jìn)行相應(yīng)的處理。那么多個(gè)客戶端的請(qǐng)求,我們就一直不關(guān)閉ServerSocket,一直等待客戶端連接,一旦建立連接拿到socket,就可以吧這個(gè)socket放到單獨(dú)的線程中,從而實(shí)現(xiàn)這個(gè)建立連接的端到端通信的socket在自己?jiǎn)为?dú)的線程中處理。這樣就能實(shí)現(xiàn)Socket的多線程處理。

  • step1:
    創(chuàng)建ServerThread,單獨(dú)處理拿到的socket,使得客戶端到服務(wù)器端的這個(gè)socket會(huì)話在一個(gè)單獨(dú)的線程中。
package com.hui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class ServerThread extends Thread{

    private Socket socket;

    //在構(gòu)造中得到要單獨(dú)會(huì)話的socket
    public ServerThread(Socket socket) {
        this.socket = socket;
    }
    
    @Override
    public void run() {
        super.run();
        InputStreamReader reader = null;
        BufferedReader bufReader = null;
        OutputStream os = null; 
        try {
            reader = new InputStreamReader(socket.getInputStream());
            bufReader = new BufferedReader(reader);
            String s = null;
            StringBuffer sb = new StringBuffer();
            while((s = bufReader.readLine()) != null){
                sb.append(s);
            }
            System.out.println("服務(wù)器:"+sb.toString());
            //關(guān)閉輸入流
            socket.shutdownInput();
            
            //返回給客戶端數(shù)據(jù)
            os = socket.getOutputStream();
            os.write(("我是服務(wù)端,客戶端發(fā)給我的數(shù)據(jù)就是:"+sb.toString()).getBytes());
            os.flush();
            socket.shutdownOutput();
        } catch (IOException e2) {
            e2.printStackTrace();
        } finally{//關(guān)閉IO資源
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
            if(bufReader != null){
                try {
                    bufReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
         
          
    }
    
}
  • step2:
    創(chuàng)建MultiThreadServer
package com.hui;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class MultiThreadServer {

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(12306);
            //死循環(huán)
            while(true){
                System.out.println("MultiThreadServer~~~監(jiān)聽~~~");
                //accept方法會(huì)阻塞,直到有客戶端與之建立連接
                Socket socket = serverSocket.accept();
                ServerThread serverThread = new ServerThread(socket);
                serverThread.start();
            }
            
            
        } catch (IOException e) {
            e.printStackTrace();
        } catch(Exception e){
            e.printStackTrace();
        }
    }

}

下面我使用兩個(gè)手機(jī),多次進(jìn)行與服務(wù)器的連接,演示如下:
總體結(jié)果:

TCP 的多線程通信
單獨(dú)看兩個(gè)手機(jī)

重要的事情說三遍!萬丈高樓平地起!萬丈高樓平地起!!萬丈高樓平地起!!!只有當(dāng)我們明白了最底層的,知識(shí)才是最牢固的。上面的講解的是基于TCP協(xié)議的socket編程。而我們后來將要講的HTTP相關(guān)的大都是基于TCP/IP協(xié)議的。一個(gè)TCP/IP協(xié)議我們又不能直接使用,Socket可以說是TCP/IP協(xié)議的抽象與包裝,然后我們就可以做相對(duì)于TCP/IP的網(wǎng)絡(luò)通信與信息傳輸了。

UDP編程

上面我們講解了基于TCP協(xié)議的Socket編程,現(xiàn)在開始我們就開始講解基于UDP協(xié)議的Socket編程了。
UDP,是User Datagram Protocol,也就是用戶數(shù)據(jù)包協(xié)議。關(guān)鍵點(diǎn)在于“數(shù)據(jù)包”。主要就是把數(shù)據(jù)進(jìn)行打包然后丟給目標(biāo),而不管目標(biāo)是否接收到數(shù)據(jù)。主要的流程就是:<u>發(fā)送者打包數(shù)據(jù)(DatagramPacket)然后通過DatagramSocket發(fā)送,接收者收到數(shù)據(jù)包解開數(shù)據(jù)。</u>

主要API:
DatagramPacket,用來包裝發(fā)送的數(shù)據(jù)
構(gòu)造方法

  • 發(fā)送數(shù)據(jù)的構(gòu)造
    DatagramPacket(byte[] buf, int length,SocketAddress address)
    DatagramPacket(byte[] buf, int length, InetAddress address, int port)
    用來將長(zhǎng)度為 length 的包發(fā)送到指定主機(jī)上的指定端口號(hào)。length 參數(shù)必須小于等于 buf.length。

  • 接收數(shù)據(jù)的構(gòu)造:
    public DatagramPacket(byte[] buf, int length)
    用來接收長(zhǎng)度為 length 的數(shù)據(jù)包。

DatagramSocket:

構(gòu)造方法
DatagramSocket()
構(gòu)造數(shù)據(jù)報(bào)套接字并將其綁定到 <u>本地主機(jī)上任何可用的端口 </u>。套接字將被綁定到通配符地址,IP 地址由內(nèi)核來選擇。

DatagramSocket(int port)
創(chuàng)建數(shù)據(jù)報(bào)套接字并將其綁定到<u>本地主機(jī)上的指定端口</u>。套接字將被綁定到通配符地址,IP 地址由內(nèi)核來選擇。

發(fā)送數(shù)據(jù)
send(DatagramPacket p)
從此套接字發(fā)送數(shù)據(jù)報(bào)包。DatagramPacket 包含的信息指示:將要發(fā)送的數(shù)據(jù)、其長(zhǎng)度、遠(yuǎn)程主機(jī)的 IP 地址和遠(yuǎn)程主機(jī)的端口號(hào)。
接收數(shù)據(jù)
receive(DatagramPacket p)
從此套接字接收數(shù)據(jù)報(bào)包。當(dāng)此方法返回時(shí),DatagramPacket 的緩沖區(qū)填充了接收的數(shù)據(jù)。數(shù)據(jù)報(bào)包也包含發(fā)送方的 IP 地址和發(fā)送方機(jī)器上的端口號(hào)。

下面開始代碼了

客戶端

主要頁(yè)面與上面的tcp一致,只不過是通訊時(shí)的方法改了。如下:

private void udp() {
        byte[] bytes = et.getText().toString().getBytes();
        try {
            /*******************發(fā)送數(shù)據(jù)***********************/
            InetAddress address = InetAddress.getByName("192.168.232.2");
            //1.構(gòu)造數(shù)據(jù)包
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, 12306);
            //2.創(chuàng)建數(shù)據(jù)報(bào)套接字并將其綁定到本地主機(jī)上的指定端口。
            DatagramSocket socket = new DatagramSocket();
            //3.從此套接字發(fā)送數(shù)據(jù)報(bào)包。
            socket.send(packet);
            /*******************接收數(shù)據(jù)***********************/
        //1.構(gòu)造 DatagramPacket,用來接收長(zhǎng)度為 length 的數(shù)據(jù)包。
            final byte[] bytes1 = new byte[1024];
            DatagramPacket receiverPacket = new DatagramPacket(bytes1, bytes1.length);
            socket.receive(receiverPacket);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tv.setText(new String(bytes1, 0, bytes1.length));
                }
            });

//            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

服務(wù)端

UDPServer

package com.hui;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UDPServer {
    public static void main(String[] args) throws IOException {

        byte[] buf = new byte[1024];
        // 一:接受數(shù)據(jù)
        // 1.創(chuàng)建接受數(shù)據(jù)的數(shù)據(jù)包
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        // 2.創(chuàng)建UPD 的 socket
        DatagramSocket socket = new DatagramSocket(12306);
        // 3.接收數(shù)據(jù)
        System.out.println("服務(wù)端開始監(jiān)聽!~~~~");
        socket.receive(packet);
        // 4.處理數(shù)據(jù)
        System.out.println("服務(wù)端:" + new String(buf, 0, buf.length));

        // 二:返回?cái)?shù)據(jù)
        DatagramPacket p = new DatagramPacket(buf, buf.length, packet.getAddress(), packet.getPort());
        socket.send(p);
        socket.close();
    }
}
UDP通信

TCP與UDP區(qū)別與使用場(chǎng)景

至此,基于TCP、UDP協(xié)議的Socket通信已經(jīng)講完了基礎(chǔ)部分。那么這兩個(gè)協(xié)議在實(shí)際中有什么區(qū)別,分別適用于什么場(chǎng)景呢?

TCP

對(duì)于TCP的數(shù)據(jù)傳輸而言,傳輸數(shù)據(jù)之前需要進(jìn)行三次握手建立穩(wěn)定的連接。建立連接通道后,數(shù)據(jù)包會(huì)在這個(gè)通道中以字節(jié)流的形式進(jìn)行數(shù)據(jù)的傳輸。由于建立穩(wěn)定連接后才開始傳輸數(shù)據(jù),而同時(shí)還是以字節(jié)流的形式發(fā)送數(shù)據(jù),所以發(fā)送數(shù)據(jù)速度較慢,但是不會(huì)造成數(shù)據(jù)包丟失。即使數(shù)據(jù)包丟失了,會(huì)進(jìn)行數(shù)據(jù)重發(fā)。同時(shí),如果收到的數(shù)據(jù)包順序錯(cuò)亂,會(huì)進(jìn)行排序糾正。

三次握手??
這個(gè)網(wǎng)絡(luò)上的解釋太多了,想詳細(xì)了解的自行去百度上Google一下。<u>簡(jiǎn)單理解</u>的就是這樣的:我家是農(nóng)村的,記得小時(shí)后爺爺在田里種地。到了晌午時(shí)間,奶奶快燒好飯后我都要去喊爺爺吃飯,因?yàn)楦赊r(nóng)活的地離家里不遠(yuǎn)不近的,我就跑到隔壁家里的平頂房上喊爺爺吃飯。我先大喊一聲“爺爺,回家吃飯啦”。爺爺如果聽到我說的話就會(huì)給我一個(gè)應(yīng)答“好的!知道了,馬上就回去,你們先吃吧!”我只有聽到了這句話,才知道爺爺這個(gè)時(shí)候能聽到我說的話,我然后就再次回答爺爺:“好的!那你快點(diǎn)!”這三句話說完,就確定了我能聽到爺爺?shù)膽?yīng)答,爺爺也能聽到我的回復(fù)。這樣我就確定我跟爺爺之間的喊話通道是正常的,如果還想對(duì)爺爺說什么話,直接說就好了。最后,爺爺聽到了我說的話,就不再回復(fù)我的話了,然后,拿起鋤頭回來了。

總結(jié)下來,就是面向連接、數(shù)據(jù)可靠,速度慢,有序的
<u>適用于需要安全穩(wěn)定傳輸數(shù)據(jù)的場(chǎng)景。例如后面要講解的HTTP、HTTPS網(wǎng)絡(luò)協(xié)議,F(xiàn)TP文件傳輸協(xié)議以及POP、SMTP郵件傳輸協(xié)議。或者開發(fā)交易類、支付類等軟件時(shí),都需要基于TCP協(xié)議的Socket連接進(jìn)行安全可靠的數(shù)據(jù)傳輸?shù)鹊?lt;/u>

UDP

對(duì)于UDP的數(shù)據(jù)傳輸而言,UDP不會(huì)去建立連接。它不管目的地是否存在,直接將數(shù)據(jù)發(fā)送給目的地,同時(shí)不會(huì)過問發(fā)送的數(shù)據(jù)是否丟失,到達(dá)的數(shù)據(jù)是否順序錯(cuò)亂。如果你想處理這些問題的話,需要自己在應(yīng)用層自行處理。
總結(jié)下來,不面向連接、數(shù)據(jù)不可靠、速度快、無序的
<u>適用于需要實(shí)時(shí)性較高不較為關(guān)注數(shù)據(jù)結(jié)果的場(chǎng)景,例如:打電話、視頻會(huì)議、廣播電臺(tái),等。</u>

_,最后的最后,歡迎拍磚。家里要蓋房子了,上海的房?jī)r(jià)傷不起~~~~

我的GitHub

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,310評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,566評(píng)論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,055評(píng)論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,303評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,799評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,683評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,899評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,135評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評(píng)論 1 282
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,528評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,844評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容

  • 個(gè)人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,078評(píng)論 0 8
  • 1.這篇文章不是本人原創(chuàng)的,只是個(gè)人為了對(duì)這部分知識(shí)做一個(gè)整理和系統(tǒng)的輸出而編輯成的,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,107評(píng)論 6 174
  • 1. 網(wǎng)絡(luò)編程概述 1.1 計(jì)算機(jī)網(wǎng)絡(luò) 是指將地理位置不同的具有獨(dú)立功能的多臺(tái)計(jì)算機(jī)及其外部設(shè)備,通過通信線路連接...
    JackChen1024閱讀 1,046評(píng)論 0 3
  • iOS網(wǎng)絡(luò)HTTP、TCP、UDP、Socket 知識(shí)總結(jié)OSI 七層模型我們一般使用的網(wǎng)絡(luò)數(shù)據(jù)傳輸由下而上共有七...
    蝸牛也有夢(mèng)想閱讀 2,420評(píng)論 0 3
  • 1.1 TCP/IP協(xié)議組 TCP/IP協(xié)議(傳輸控制協(xié)議)由網(wǎng)絡(luò)層的IP協(xié)議和傳輸層的TCP協(xié)議組成 IP層負(fù)責(zé)...
    F麥子閱讀 2,803評(píng)論 0 25