第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

設(shè)置 Java Socket 選項(xiàng)

1. 前言

前面章節(jié)介紹了 Java TCP、UDP Socket 編程方法,按照文中介紹的方法去編寫 Socket 程序,是完全可以正常工作的。其實(shí),TCP/IP 協(xié)議棧允許你對 Socket 做一些定制,比如設(shè)置 Socket 的接收、發(fā)送緩沖區(qū)的大小,這就是常說的 Socket 選項(xiàng)。

本文首先會(huì)以 Linux 系統(tǒng)為例,介紹操作系統(tǒng) Socket 選項(xiàng)的基本概念,然后再介紹 Java 中如何去設(shè)置 Socket 選項(xiàng)。

2. Socket 選項(xiàng)的概念

操作系統(tǒng)協(xié)議棧支持的 Socket 選項(xiàng)參數(shù)有很多,匯總起來如下圖所示:

圖片描述

從圖中可以看出,Socket 選項(xiàng)按照級別進(jìn)行分類,級別有很多種,但是總結(jié)起來分兩類:

  • 通用 Socket 級別的選項(xiàng)。枚舉值為 SOL_SOCKET。
  • 協(xié)議相關(guān)的選項(xiàng)。協(xié)議棧為我們提供了控制所有協(xié)議的選項(xiàng),比如 IP、IPv6、TCP、UDP、ICMP 等。枚舉值的格式為 IPPROTO_XXX,XXX 代表協(xié)議。

每一種選項(xiàng)級別下面包含了很多選項(xiàng)參數(shù)。比如,通用 Socket 選項(xiàng)的級別枚舉值是 SOL_SOCKET,其下面包含 SO_RCVBUF 和 SO_SNDBUF 選項(xiàng)參數(shù);IP 協(xié)議選項(xiàng)的級別的枚舉值是 IPPROTO_IP,其下面包含 IP_TTL、IP_TOS 等選項(xiàng)參數(shù)。

在 Linux 系統(tǒng)下,所有的選項(xiàng)參數(shù)都可以在幫助手冊里面查找,具體方法如下:

通用 Socket 級別選項(xiàng)參數(shù)

man 7 socket

IP 協(xié)議級別選項(xiàng)參數(shù):

man 7 ip

IPv6 協(xié)議級別選項(xiàng)參數(shù):

man 7 ipv6

TCP 協(xié)議級別選項(xiàng)參數(shù):

man 7 tcp

UDP 協(xié)議級別選項(xiàng)參數(shù):

man 7 udp

Socket 選項(xiàng)參數(shù)最終是如何設(shè)置到協(xié)議棧的呢?協(xié)議棧提供了 getsockopt() 和 setsockopt() 兩個(gè) C 語言函數(shù),分別用于獲取和設(shè)置選項(xiàng)參數(shù)。

調(diào)用兩個(gè)函數(shù)所需要包含的頭文件,以及他們的聲明如下:

#include <sys/types.h> 
#include <sys/socket.h>

int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

如果你對系統(tǒng)本身的 Socket 選項(xiàng)感興趣,可以通過 man 查找相關(guān)幫助。本節(jié)重點(diǎn)介紹通用 Socket 選項(xiàng)。

3. 通用 Socket 選項(xiàng)

通用 Socket 選項(xiàng)的 level 枚舉值是 SOL_SOCKET。
表格中選項(xiàng)名稱不用多說,數(shù)據(jù)類型列表示選項(xiàng)值的類型,大多數(shù)是整形,還有一些是結(jié)構(gòu)體類型。有的選項(xiàng)是既可以設(shè)置值也可以讀取值,用 set 表示;有的選項(xiàng)只能讀取值,用 get 表示。常見選項(xiàng)參數(shù)如下:

選項(xiàng)名稱 數(shù)據(jù)類型 get 或 set 說明
SO_BROADCAST int set 設(shè)置 Socket 可以進(jìn)行局域網(wǎng)廣播,目標(biāo) IP 需要填網(wǎng)段的廣播地址或者是統(tǒng)一受限廣播地址 255.255.255.255。
SO_KEEPALIVE int set 用于設(shè)置 TCP 連接的?;睿话愫苌儆?。
SO_LINGER struct linger set 用于設(shè)置當(dāng) TCP 連接已經(jīng)關(guān)閉,但是未發(fā)送數(shù)據(jù)等待時(shí)間。通常設(shè)置 SO_LINGER 等待時(shí)間為 0,解決大量 TIME_WAIT 狀態(tài)的問題。
SO_OOBINLINE int set 用于設(shè)置將“帶外數(shù)據(jù)”作為普通數(shù)據(jù)流來處理。
SO_RCVBUF int set 設(shè)置 Socket 接收緩沖區(qū)大小。
SO_REUSEADDR int set 用于設(shè)置在調(diào)用 bind() 函數(shù)時(shí),重用已經(jīng) bind 的 Socket 地址。
SO_SNDBUF int set 設(shè)置 Socket 發(fā)送緩沖區(qū)大小。

4. 常用選項(xiàng)說明

下來,我們對 Socket 編程中常用的 Socket 選項(xiàng)重點(diǎn)介紹。

4.1 SO_REUSEADDR

TCP 連接關(guān)閉過程中,主動(dòng)關(guān)閉的一方會(huì)處于 TIME_WAIT 狀態(tài),要等待 2MSL 時(shí)間。而服務(wù)器在工作過程中有可能由于配置的改變而要重啟,或者是由于程序異常奔潰要重新啟動(dòng)。在這種情況下,如果服務(wù)器監(jiān)聽的 Socket 處于 TIME_WAIT 狀態(tài),那么調(diào)用 bind 方法綁定 Socket 就會(huì)失敗。如果要等待 2MSL 時(shí)間,對于服務(wù)器來說是難以接受的。要想解決此問題,需要給監(jiān)聽 Socket 設(shè)置 SO_REUSEADDR 選項(xiàng)。

Java 的 java.net.ServerSocket 類提供了 setReuseAddress 方法,可以用以設(shè)置 SO_REUSEADDR 選項(xiàng),如下:

        ServerSocket ss = null;
        try {
            ss = new ServerSocket();
            ss.setReuseAddress(true);
            ss.bind(new InetSocketAddress(8022));
            ss.accept();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ss != null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
  • 注意:
  • SO_REUSEADDR 選項(xiàng)需要在 bind 方法調(diào)用前設(shè)置,所以要?jiǎng)?chuàng)建一個(gè)未綁定的 ServerSocket 對象,然后手動(dòng)執(zhí)行 bind 操作。

4.2 SO_KEEPALIVE

SO_KEEPALIVE 是協(xié)議棧提供的一種連接?;顧C(jī)制,一般是用在 TCP 協(xié)議中。主要目的是當(dāng)通信雙方長時(shí)間沒有數(shù)據(jù)交互,然而 Socket還沒有被關(guān)閉,協(xié)議棧會(huì)向?qū)Ψ桨l(fā)送一個(gè) Heartbeat 消息期望對方回復(fù)一個(gè) ACK,如果對方能回復(fù)說明連接是正常的,如果對方不能回復(fù),嘗試幾次以后就會(huì)關(guān)閉連接。系統(tǒng)?;畹臅r(shí)間一般是 2 小時(shí)。

Java 的 java.net.Socket 類提供了 setKeepAlive 方法,可以用以設(shè)置 SO_KEEPALIVE 選項(xiàng),如下:

    sock.setKeepAlive(true);

4.3 SO_LINGER

SO_LINGER 是用來設(shè)置“連接關(guān)閉以后,未發(fā)送完的數(shù)據(jù)包還可以在協(xié)議棧逗留的時(shí)間”。java.net.Socket 提供了 setSoLinger 方法可以設(shè)置 SO_LINGER 選項(xiàng)。原型如下:

public void setSoLinger(boolean on, int linger) throws SocketException
  • 如果設(shè)置 on 為 false,則該選項(xiàng)的值被忽略,協(xié)議棧會(huì)采用默認(rèn)行為。close 調(diào)用會(huì)立即返回給調(diào)用者,協(xié)議棧會(huì)盡可能將 Socket 發(fā)送緩沖區(qū)未發(fā)送的數(shù)據(jù)發(fā)送完成。

  • 如果設(shè)置 on 為 true,但是 linger 為 0,當(dāng)你調(diào)用了 close() 方法以后,協(xié)議棧將丟棄保留在 Socket 發(fā)送緩沖區(qū)中未發(fā)送完的數(shù)據(jù),然后向?qū)Ψ桨l(fā)送一個(gè) RST。這樣連接很快會(huì)被關(guān)閉,不會(huì)進(jìn)入 TIME_WAIT 狀態(tài),這也是一個(gè)避免“由于大量 TIME_WAIT 狀態(tài)的 Socket 導(dǎo)致連接失敗“的解決辦法。

  • 如果設(shè)置 on 為 true ,但是 linger 的取值大于 0,當(dāng)你調(diào)用了 close() 方法以后,如果 Socket 發(fā)送緩沖區(qū)還有未發(fā)送完的數(shù)據(jù),那么系統(tǒng)會(huì)等待一個(gè)指定的時(shí)間,close() 才返回。注意,這種情況下 close() 方法返回,并不能保證 Socket 發(fā)送緩沖區(qū)中未發(fā)送的數(shù)據(jù)被成功發(fā)送完。

  • 注意:
  • 參數(shù) linger 的單位是。
sock.setSoLinger(true, 20);

4.4 SO_RCVBUF

SO_RCVBUF 很好理解,用于設(shè)置 Socket 的接收緩沖區(qū)大小。TCP 一般不需要設(shè)置,UDP 可能需要設(shè)置。java.net.Socket 類提供了 setReceiveBufferSize 方法可以設(shè)置接收緩沖區(qū)的大小。

sock.setReceiveBufferSize(16384);

4.5 SO_SNDBUF

SO_SNDBUF 也很好理解,用于設(shè)置 Socket 的發(fā)送緩沖區(qū)大小。一般不需要設(shè)置,采用系統(tǒng)默認(rèn)大小即可。java.net.Socket 類提供了 setSendBufferSize 方法可以設(shè)置發(fā)送緩沖區(qū)的大小。

sock.setSendBufferSize(16384);

4.6 SO_OOBINLINE

SO_OOBINLINE 用于設(shè)置將“帶外數(shù)據(jù)”作為普通數(shù)據(jù)流來處理。java.net.Socket 類提供了 setOOBInline 方法可以設(shè)置 SO_OOBINLINE 選項(xiàng)。

sock.setOOBInline(true);

4.7 TCP_NODELAY

TCP_NODELAY 用于關(guān)閉 Nagle 算法,一般是用在實(shí)時(shí)性要求比較高的場景。java.net.Socket 提供了 setTcpNoDelay 方法用于設(shè)置 TCP_NODELAY 選項(xiàng)。

 sock.setTcpNoDelay(true);

5 小結(jié)

本節(jié)重點(diǎn)是介紹在 java 中設(shè)置常用 Socket 選項(xiàng)的方法。當(dāng)然,我們是從 Linux 系統(tǒng)本身提供的 Socket 選項(xiàng)開始的,我們也介紹了在 linux 系統(tǒng)中如何查找 Socket 選項(xiàng)的方法。了解操作系統(tǒng)對 Socket 選項(xiàng)的支持,可以讓你形成一個(gè)完整的認(rèn)識(shí)。

文中列出了常用 Socket 選項(xiàng)的應(yīng)用場景。SO_REUSEADDR 是服務(wù)器必須要設(shè)置的一個(gè)選項(xiàng),也只有服務(wù)器才需要此功能。TCP_NODELAY 是在開發(fā)實(shí)時(shí)性要求很高的程序時(shí),必須要設(shè)置的,比如音視頻通信系統(tǒng)。

SO_LINGER 是在服務(wù)器端解決“由于 TIME_WAIT 過多,導(dǎo)致連接失敗的問題”時(shí)的一個(gè)常用方法。其他選項(xiàng),可以根據(jù)需要選擇是否開啟。