亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

SOCKET 協議

Socket 是傳輸層協議的具體軟件實現,它封裝了協議底層的復雜實現方法,為開發人員提供了便利的網絡連接。Socket 是網絡編程的基石,像 Http 的請求,MySQL 數據庫的連接等絕大部分的網絡連接都是基于 Socket 實現的。

1. 傳輸層協議

傳輸層有 TCP/UDP 兩種連接方式,所以對應的 Socket 也有兩種不同實現方式,掌握 Socket 的前提是了解清楚這兩種協議。

1.1 TCP 協議

面向連接,且具備順序控制和重發機制的可靠傳輸。他的可靠性是在于傳輸數據前要先建立連接,確保要傳輸的對方有響應才進行數據的傳輸。因此 TCP 有個經典的 3 次握手和 4 次揮手。

3 次握手

握手的目的是為了相互確認通信雙方的狀態都是正常的,沒有問題后才會進行正式的通信:

  1. 第一次握手:客戶端發送請求連接的消息給服務端,但發出去的消息是否到達并不清楚,要基于第二次握手的反饋;
  2. 第二次握手:服務端返回消息說明客戶端的消息收到了,此時它也糾結了,我的反饋信息對方有沒有收到,所以得依托第三次得握手;
  3. 第三次握手:客戶端反饋第二次握手的消息收到了。至此,通信雙發的發送消息和接受消息能力都得到了檢驗。

3 次握手的整個過程看著似乎有點過于謹慎,但是互聯網的初期網絡基礎設施是很落后的,丟包的概率非常大的。而且這個過程也只是在通信前期建立連接的時候進行,3 次握手過后就是正常的消息傳輸了。

4 次揮手

4 次揮手的目的跟 3 次握手目的是一樣的,謹慎的確保雙方消息狀態的準確:

  1. 第一次揮手:客戶端(服務端也可以主動斷開)向服務端說明想要關閉連接;
  2. 第二次揮手:服務端首先回復第一次的消息已經收到。但是并不是立馬關閉,因為此時服務端可能還有數據在傳輸中;
  3. 第三次揮手:待到數據傳輸都結束后,服務端向客戶端發出消息,告知一切都準備好了,我要斷開連接了;
  4. 第四次揮手:客戶端收到服務端的斷開信息后,給予確認。服務端收到確認后正式關閉??蛻舳俗约阂舶l出關閉信息,因為服務端已經關閉了無法確認,等到一段時間后客戶端正式關閉。

1.2 UDP 協議

UDP 是一種不可靠的傳輸機制,但是它的數據報文比 TCP 小,所以相同數據的傳輸 UDP 所需的帶寬更少,傳輸速度更快。它不要事先建立連接,知道對方的地址后直接數據包就扔過去,也不保證對方有沒有收到。

2. 連接方式

我們知道 TCP 數據發送前要建立連接,UDP 不需要,而 Socket 的連接又有如下區分:

2.1 長連接

  1. 兩個節點建立連接并保持不斷開的狀態;
  2. 兩邊雙向自由的進行數據傳輸;
  3. 直到數據全部交互結束才斷開。

2.2 短連接

  1. 節點 A 向節點 B 建立連接;
  2. A 發送數據給 B;
  3. 一條數據發送完立馬斷開。

2.3 適用場景

  • 連接的建立需要開銷,頻繁的重建連接容易造成資源浪費,長連接適合客戶端和服務端都比較明確且傳輸數據比較大的情況
  • 每臺服務器的連接數都是有限制的,如果太多的長連接阻塞會影響到新連接的建立。Http 是一種短連接的方式,這樣有利于他處理高并發的請求。有一種 slowHttp 的攻擊,就是利用 Http 協議的特點,故意制造了一個很長的報文,然后每次發送很少量的數據,使請求一直占用最終耗盡服務器的連接。所以 Http 雖然是短連接,但是一般是等到數據傳輸完成才斷開的,我們應該根據具體業務設置 Http 請求的超時時間。

3. socket 編程

下面的代碼實現了一個 Socket 的服務端服務和一個客戶端,服務端在 6000 端口上面監聽連接,收到客戶端的連接后向客戶端發出 hello 問候語,客戶端打印出服務端發送過來的消息。

3.1 服務端

public class Server {
    public static void main(String[] args) {
        // 創建一個serverSocket監聽本地的6000端口
        try(ServerSocket server = new ServerSocket (6000)) {
            // 當有客戶端連接上就建立一個socket通道
            Socket socket = server.accept();
            OutputStream outputStream = socket.getOutputStream();
            // 有客戶端連接上來就主動發送問候語
            outputStream.write("hello".getBytes());
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.2 客戶端

public class Client {
    public static void main(String[] args) {
        // 根據{IP}+{port}與服務器建立連接
        try( Socket socket=new Socket("127.0.0.1",6000)){
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 打印服務端發送的信息
            System.out.println("Client:"+bufferedReader.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. websocket

Websocket 是一種升級版的 Http 服務,傳統的 Http 服務都是客戶端發起,服務端響應,而 Websocket 支持服務端向客戶端主動推送消息,增強了瀏覽器的交互場景。Websocket 也是應用層協議,跟 Http 一樣具體的實現都要基于 Socket,除此之外并沒有什么特殊。
websocket

5. 小結

幾乎所有的軟件都需要通信,而幾乎所有的通信都是基于 Socket 實現的,Socket 從軟件的層面屏蔽了傳輸層的細節,開發人員可以很方便的使用。Socket 起源于 Unix,而 Unix/Linux 基本哲學之一就是“一切皆文件”,使用的時候就打開,不用就關閉。