老生常談Java?網(wǎng)絡編程?——?Socket?詳解
1|0構(gòu)造socket
在【客戶端/服務端】的通信模式中,客戶端需要主動構(gòu)造與服務器連接的 Socket,構(gòu)造方法有以下幾種重載形式:
Socket() Socket(InetAddress address, int port) throws UnknownHostException,IOException Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException Socket(String host, int port) throws UnknownHostException,IOException Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException Socket(Proxy proxy)
除了第一個不帶參數(shù)的構(gòu)造方法,其他構(gòu)造方法都會試圖建立與服務器的連接,一旦連接成功,就返回 Socket 對象,否則拋出異常
1. 設定等待建立連接的超時時間
當客戶端的 Socket 構(gòu)造方法請求與服務器連接時,可能要等待一段時間。在默認情況下,Socket 構(gòu)造方法會一直等待下去,直到連接成功,或者出現(xiàn)異常。Socket 構(gòu)造方法請求連接時,受底層網(wǎng)絡的傳輸速度的影響,可能會處于長時間的等待狀態(tài)。如果希望限定等待連接的時間,就需要使用第一個不帶參數(shù)的構(gòu)造方法
Socket socket = new Socket();
SocketAddress remoteAddr = new InetSocketAddress("1ocalhostn", 8000);
// 參數(shù)endpoint指定服務器的地址,參數(shù)timeout設定的超時時間(ms)
// 如果參數(shù)timeout被設為0則表示永遠不會超時
socket.connect(remoteAddr, 60000);以上代碼用于連接到本地機器上的監(jiān)聽 8000 端口的服務器程序,等待連接的最長時間為一分鐘。如果在一分鐘內(nèi)連接成功,則 connect() 方法順利返回,如果在一分鐘內(nèi)出現(xiàn)某種異常則拋出該異常,如果在一分鐘后既沒有連接成功,也沒有出現(xiàn)異常,那么會拋出 SocketTimeoutException
2. 設定服務器的地址
除了不帶參數(shù)的構(gòu)造方法,其他構(gòu)造方法都需要在參數(shù)中設定服務器的地城,包括服務器的 IP 或主機名,以及端口
?
Socket socket = new Socket();
SocketAddress remoteAddr = new InetSocketAddress("1ocalhostn", 8000);
// 參數(shù)endpoint指定服務器的地址,參數(shù)timeout設定的超時時間(ms)
// 如果參數(shù)timeout被設為0則表示永遠不會超時
socket.connect(remoteAddr, 60000);InetAddress 類表示主機的P地址,提供了一系列靜態(tài)工廠方法用于構(gòu)造自身實例
// 返回本地主機的IP地址、
InetAddress addr1 = inetAddress.getLocalHost();
// 返回代表 "222.34.57” 的 IPv4 地址
InetAddress addr2 = InetAddress.getByName("222.34.5.7");
// 返同代表 ”2001:DB8:2DE::E13" 的 IPv6 地址
InetAddress addr3 = InetAddress.getByName("2001:DB8:2DE::E13");
// 返回主機名為 "www.javathinker.net" 的 IP 地址
InetAddress addr4 = InetAddress.getByName ("www.javathinker.net");3. 設定客戶端的地址
在一個 Socket 對象中既包含遠程服務器的 IP 地址和端口信息,也包含本地客戶端的 IP 地址和端口信息。在默認情況下,客戶端的 IP 地址來自客戶程序所在的主機,客戶端的端口則由操作系統(tǒng)隨機分配。Socket 類還有兩個構(gòu)造方法允許顯式地設置客戶端的 IP 地址和端口
Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException
如果一個主機同時屬于兩個以上的網(wǎng)絡,它就可能擁有兩個以上 IP 地址,例如一個主機在 Internet 網(wǎng)絡中的 IP 地址為 “222.67,1.34”,在一個局域網(wǎng)中的 IP 地址為 “1125.4.3",假定這個主機上的客戶程序希望和同一個局城網(wǎng)上的一個地址為 “112.5.4.4:8000” 的服務器程序通信,客戶端可按照如下方式構(gòu)造 Socket 對象
InetAddress remoteAddr = InetAddress.getByName("112.5,4.45");
InetAddress localAddr = InetAddress.getByName("112.5.4.3");
//客戶端使用口2345
Socket socket = new Socket(remoteAddr, 8000, localAddr, 2345);4. 客戶連接服務器時可能拋出的異常
當 Socket 的構(gòu)造方法請求連接服務器時,可能會拋出以下異常:
- UnknownHostException:無法識別主機的名字或 IP 地址
- ConnectException:沒有服務器進程監(jiān)聽指定的端口,或者服務器進程拒絕連接
- SocketTimeoutException:等待連接超時
- BindException:無法把Socket 對象與指定的本地 IP 地址或端口綁定
5. 使用代理服務器
在實際應用中,有的客戶程序會通過代理服務器來訪問遠程服務器。代理服務器有許多功能,比如能作為防火墻進行安全防范,或者提高訪問速度,或者具有訪問特定遠程服務器的權限
String proxyIP = "myproxy.abc.oom"; // 代理服務器地址
int proxyPort = 1080; // 代理服務器端口
// 創(chuàng)建代理對象
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(proxyIP, proxyPort));
Socket socket new Socket(proxy);
//連接到遠程服務器
socket.connect(new InetSocketAddress("www.javathinker.net", 80));ProxyType 類表示代理服務器的類型,有以下可選值:
- Proxy.Type.SOCKS:在分層的網(wǎng)絡結(jié)構(gòu)中,SOCKS 是位于會話層的代理類型
- Proxy.Type.HTTP:在分層的網(wǎng)絡結(jié)構(gòu)中,HTTP 是位于應用層的代理類型
- Proxy.Type.DIRECT:不使用代理,直接連接遠程服務器
6. InetAddress 地址類的用法
InetAddress 類表示主機的IP 地址,InetAddress 類的靜態(tài)工廠方法給 getByName() 用于構(gòu)造自身的實例
// 返回代表 "222.34.5.7" 的 IPv4 地址
InetAddress addr2 = InetAddress,getByName("222.34.5.7");
// 返回主機名為 "www.javathinker.net" 的 IP 地址
InetAddress addr4 = InetAddress.getByName("www.javathinker.net");InetAddress 還提供了獲取相應的主機名的兩種方法:
getHostname():首先從 DNS 緩存中查找與 IP 地址匹配的主機名,如果不存在,再通過 DNS 服務器查找,如果找到,則返回主機名,否則返回 IP 地址getCanonicalHostName():通過 DNS 服務器查找與 IP 地址匹配的主機名,如果找到則返回主機名,否則返問 IP 地址
以上兩種方法的區(qū)別在于 getHostname() 會先查找 DNS 緩存,減少查找 DNS 服務器的概率,提高查找性能。而 getCanonicalHostName() 總是查找 DNS 服務器,確保獲得當前最新版本的主機名
InetAddress 類還提供了兩個測試能否從本地主機連接到特定主機的方法:
public boolean isReachable(int timeout) throws IOException public boolean isReachable(NefworkInterface interface, int ttl, int timeout) throws IOException
如果遠程主機在參數(shù) timeout(ms)指定的時間內(nèi)做出回應,以上方法返回true,否則返回 false,如果出現(xiàn)網(wǎng)絡錯誤則拋出 IOException。第二種方法還允許從參數(shù)指定的本地網(wǎng)絡接口建立連接,以及 TTL(IP 數(shù)據(jù)包被丟棄前允許存在的時間)
7. NetworkInterface 類的用法
NetworkInterfiace 類表示物理上的網(wǎng)絡接口,它有兩種構(gòu)造自身實例的靜態(tài)工廠方法,這兩種方法都聲明拋出 SocketException
// 參數(shù) name 指定網(wǎng)絡接口的名字,如果不存在與名字對應的網(wǎng)絡接口,就返回 null getByName(String name) // 參數(shù) address 指定網(wǎng)絡接口的 IP 地址,如果不存在與 IP 地址對應的網(wǎng)絡接口,就返回 null getByInetAddress(InetAddress address)
NetworkInterface 類的以下方法用于獲取網(wǎng)絡接口的信息
// 返回網(wǎng)絡接口的名字 public String getName() // 返回和網(wǎng)絡接口綁定的所有 IP 地址,返回值為 Enumeration 類型,里面存放了表示 IP 地址的 InetAddress 對象 public Enumeration getInetAddresses()
2|0獲取 Socket 的信息
在一個 Socket 對象中同時包含了遠程服務器的 IP 地址和端口信息,以及客戶本地的 IP 地址和端口信息。此外,從 Socket 對象中還可以獲得輸出流和輸入流,分別用于向服務器發(fā)送數(shù)據(jù),以及接收從服務器端發(fā)來的數(shù)據(jù)
以下方法用于獲取 Socket 的有關信息
// 獲得遠程被連接進程的IP地址 getInetAddress() // 獲得遠程被連接進程的端口 getPort() // 獲得本地的IP地址 getLocalAddress() // 獲得本地的端口 getLocalPort() // 獲得輸入流,如果Socket還沒有連接,或者已經(jīng)關團,或者已經(jīng)通過shutdownInput()方法關閉輸入流,那么此方法會拋出IOException getInputStream() // 獲得輸出流,如果Socket還沒有連接,或者已經(jīng)關閉,或者已經(jīng)通過shutdownOutput()方法關閉輸出流,那么此方法會拋出 IOException getOutputStream()
3|0關閉 Socket
當客戶與服務器的通信結(jié)束時,應該及時關閉 Socket,以釋放 Socket 占用的包括端口在內(nèi)的各種資源。Socket 的 close() 方法負責關閉 Socket,如果一個 socket 對象被關閉,就不能再通過它的輸入流和輸出流進行 IO 操作,否則會導致 IOException
Socket 類提供了三個狀態(tài)測試方法
// 如果Socket沒有關閉,則返回false,否則返回true isClosed() // 如果Socket曾經(jīng)連接到遠程主機,不管當前是否已經(jīng)關閉,都返回true。如果Socket從未連接到遠程主機,就返回false isConnected() // 如果Socket已經(jīng)與一個本地端口綁定,則返回true,否則返回false isBound()
如果要判斷一個 Socket 對象當前是否處于連接狀態(tài),可采用以下方式
String isConnected = socket.isConnected() && !socket.isClosed();
4|0半關閉 Socket
進程 A 與進程 B 通過 Socket 通信,假定進程 A 輸出數(shù)據(jù),進程 B 讀入數(shù)據(jù),進程 A 如何告訴進程 B 所有數(shù)據(jù)已經(jīng)輸出完畢呢?有幾種處理辦法:
如果進程 A 與進程 B 交換的是字符流,并且都一行一行地讀寫數(shù)據(jù),那么可以事先約定以一個特殊的標志作為結(jié)束標志,例如以字符串 “bye” 作為結(jié)束標志,當進程 A 向進程 B 發(fā)送一行字符串 “bye”,進程 B 讀到這一行數(shù)據(jù)后,就停止讀取數(shù)據(jù)
進程 A 先發(fā)送一個消息,告訴進程 B 所發(fā)送的正文的長度,然后發(fā)送正文。進程 B 先獲知進程 A 將發(fā)送的正文的長度,接下來只要讀取該長度的字符或者字節(jié),就停止讀取數(shù)據(jù)
進程 A 發(fā)完所有數(shù)據(jù)后,關閉 Socket,當進程 B 讀入了進程 A 發(fā)送的所有數(shù)據(jù)后,再次執(zhí)行輸入流的 read() 方法時,該方法返回 “-1”,如果執(zhí)行 BufferedReader 的 readLine() 方法,那么該方法返回 null
ByteArrayOutputstream bufferenew = ByteArrayOutputstream();
byte[] buff = new byte[1024);
int len = -1;
while((len = socketIn.read(buff)) != -1) {
buffer.write(buff, 0, len);
}- 當調(diào)用 Socke t的 close() 方法關閉 Socket 后,它的輸出流和輸入流也都被關閉。有的時候,可能僅僅希望關閉輸出流或輸入流之一,此時可以采用 Socket 類提供的半關閉方法
shutdownInput() // 關閉輸入流 shutdownOutput() // 關團輸出流
假定進程 A 執(zhí)行以下代碼,先向進程 B 發(fā)送一個字符串,等到進程 B 接收到這個字符串后,進程 A 再調(diào)用 Socket 的 shutdownOutput() 方法關閉輸出流,接下來進程 A 不允許再輸出數(shù)據(jù),但是仍可以通過輸入流讀入數(shù)據(jù)
// 發(fā)出請求信息
String data = ...;
OutputStream socketOut = socket.getOutputStream();
socketOut.write(data.getBytes());
socketOut.flush();
// 讀取響應
InputStream socketIn = socket.getInputStream();
if(服務器端返回提示信息,表明已經(jīng)接收到客戶端的所有請求數(shù)據(jù))
socket.shutdownOutput(); //關閉輸出流
//繼續(xù)通過socketIn讀取數(shù)據(jù)
...值得注意的是,先后調(diào)用 Socket 的 shutdownInput() 和 shutdownOutput() 方法,僅僅關閉了輸入流和輸出流,并不等價于調(diào)用 Socket 的 close() 方法。在通信結(jié)束后,仍然要調(diào)用 Socket 的 close() 方法,因為只有該方法才會釋放 Socket 占用的資源,比如占用的本地端口等
Socket 類還提供了兩種狀態(tài)測試方法,用來判斷輸入流和輸出流是否關閉
public boolean isInputShutdown() // 如果輸入流關閉,則返回true,否則返回false public boolean isOutputShutdown() // 如果輸出流關閉,則返回true,否則返回false
5|0設置 Socket 的選項
1. TCP_NODELAY
表示立即發(fā)送數(shù)據(jù)。在默認情況,下發(fā)送數(shù)據(jù)采用 Negale 算法,發(fā)送方發(fā)送的數(shù)據(jù)不會立刻被發(fā)出,而是先放在緩沖區(qū)內(nèi),等緩沖區(qū)滿了再發(fā)出。發(fā)送完一批數(shù)據(jù)后,會等待接收方對這批數(shù)據(jù)的回應,然后發(fā)送下一批數(shù)據(jù)。此算法法適用于發(fā)送方需要發(fā)送大批量數(shù)據(jù)并且接收方會及時做出回應的場合,這種算法通過減少傳輸數(shù)據(jù)的次數(shù)來提高通信效率
如巢發(fā)送方持續(xù)地發(fā)送小批量的數(shù)據(jù)。并且接收方不一定會立即發(fā)送響應數(shù)據(jù),那么 Negale 算法會使發(fā)送方運行得很慢,對于GU程序,比如網(wǎng)絡游戲程序(服務器需要實時跟蹤客戶端鼠標的移動),這個問題尤其突出
TCP_NODEALY 的默認值為 false,表示采用 Negale 算法,如果調(diào)用 setTcpNoDelay(true) 方法,就會關閉 Socket 的緩沖,確保數(shù)據(jù)被及時發(fā)送
if(!socket.getTcpNoDelay())
socket.setTcpNoDelay(true);2. SO_RESUSEADDR
表示是否允許重用 Socket 所綁定的本地地址。當接收方通過 Socket 的 close() 方法關閉 Socket 時,如果網(wǎng)絡上還有發(fā)送到這個 Socket 的數(shù)據(jù),那么底層的 Socket 不會立刻釋放本地端口,而是會等待一段時間,確保接收到了網(wǎng)絡上發(fā)送過來的延遲數(shù)據(jù),再釋放端口。Socket 接收到延遲數(shù)據(jù)后,不會對這些數(shù)據(jù)做任何處理。Socket 接收延遲數(shù)據(jù)的目的是,確保這些數(shù)據(jù)不會被其他碰巧綁定到同樣端口的新進程接收到
客戶程序一般采用隨機端口,因此出現(xiàn)兩個客戶程序綁定到同樣端口的可能性不大。許多服務器程序都使用固定的端口。當服務器程序被關閉后,有可能它的端口還會被占用一段時間,如果此時立刻在同一臺主機上重啟服務器程序,由于端口已經(jīng)被占用,使得服務感程序無法綁定到該端口,導致啟動失敗
為了確保當一個進程關閉了 Socket 后,即便它還沒釋放端口,同一臺主機上的其他進要也可以立刻重用該端口,可以調(diào)用 Socke 的 setResuseAddress(ture) 方法
if(!socket.getResuseAddress())
socket.setResuseAddress(true);值得注意的是 socket.setResuseAddress(true) 方法必須在 Socket 還沒有被綁定到一個本地端口之前調(diào)用,否則執(zhí)行無效
3. SO_TIMEOUT
表示接收數(shù)據(jù)時的等待超時時間。當通過 Socket 的輸入流讀數(shù)據(jù)時,如果還沒有數(shù)據(jù),就會等待。Socket 類的SO_TIMEOUT 選項用于設定接收數(shù)據(jù)的等待超時時間,單位為 ms,它的默認值為0,表示會無限等待,永遠不會超時
以下代碼把接收數(shù)據(jù)的等待超時時間設為三分鐘
if(socket.getTimeout() == 0)
socket.setTimeout(60000 * 3);Socket 的 setTimeout() 方法必須在接收數(shù)據(jù)之前執(zhí)行才有效
4. SO_LINGER
表示與執(zhí)行 Socket 的 close() 方法時,是否立即關閉底層的 Socket。在默認情況下執(zhí)行 Socket 的 close() 方法,該方法會立即返回,但底層的 Socket 實際上并不立即關閉,它會延遲一段時間,直到發(fā)送完所有剩余的數(shù)據(jù),才會真正關閉 Socket
如果執(zhí)行以下方法
socket.setSoLinger(true,0);
那么執(zhí)行 Socket 的 close() 方法,該方法也會立即返回而且底層的 Socket 也會立即關閉,所有未發(fā)送完的數(shù)據(jù)被丟棄
如果執(zhí)行以下方法
socket.setSoLinger(true,3600);
那么執(zhí)行 Socket 的 close() 方法,該方法不會立即返回,而是進入阻塞狀態(tài),同時,底層的 Socket 會嘗試發(fā)送剩余的數(shù)據(jù)。只有滿足以下兩個條件之一,close() 方法才返回:
- 底層的 Socket 已經(jīng)發(fā)送完所有的剩余數(shù)據(jù)
- 盡管底層的 Socket 還沒有發(fā)送完所有的剩余數(shù)據(jù),但己經(jīng)阻塞了 3600s,此時
close()也會返回,未發(fā)送的數(shù)據(jù)被丟棄
5. SO_RCVBUF
表示接收數(shù)據(jù)的緩沖區(qū)的大小。一般說來,傳輸大的連續(xù)的數(shù)據(jù)塊,比如基于 HTTP 或 FTP 的通信,可以使用較大的緩沖區(qū),這可以減少傳輸數(shù)據(jù)的次數(shù),提高傳輸數(shù)據(jù)的效率。而對于交互式的通信方式,比如 Telnet 和網(wǎng)絡游戲,則應該采用小的緩沖區(qū),確保小批量的數(shù)據(jù)能及時發(fā)送給對方
6. SO_SNDBUF
表示發(fā)送數(shù)據(jù)的緩沖區(qū)的大小
7. SO_KEEPALIVE
表示對于長時間處于空閑狀態(tài)的 Socket,是否要自動把它關團。當 SO_KEEPALIVE 選項為 tue 時,表示底層的 TCP 實現(xiàn)會監(jiān)視該連接是否有效連接處于空閑狀態(tài),即連接的兩端沒有互相傳送數(shù)據(jù)超過了 2 小時,本地的 TCP 實現(xiàn)發(fā)送一個數(shù)據(jù)包給遠程的 Socket,如果遠程 Socke 沒有返回響應,TCP 實現(xiàn)就會持續(xù)嘗試發(fā)送 11 分鐘,直到接收到響應為止。如果在 12 分鐘內(nèi)未收到響應,TCP 實現(xiàn)就會自動關閉本地 Socket,斷開連接
SO_KEEPALIVE 選項的默認值為 false,表示 TCP 不會監(jiān)視連接是否有效,不活動的客戶端可能會永久存在下去,而不會注意到服務器已經(jīng)崩潰
8. IP 服務類型選項
當用戶通過郵局發(fā)送普通信、掛號信或者快件時,實際上選擇了郵局提供的不同的服務。發(fā)送普通信的價格最低,但發(fā)送速度慢,并且可靠性沒有保證。發(fā)送掛號信的價格稚高,但可靠性有保證。發(fā)送快件的價格最高,發(fā)送速度最快,并且可靠性有保證
在 Internet 上傳輸數(shù)據(jù)也分為不同的服務類型,它們有不同的定價。用戶可以根據(jù)自己的需求,選擇不同的服務類型。例如發(fā)送視頻需要較高的帶寬,快速到達目的地,以保證接收方看到連續(xù)的畫面,而發(fā)送電子郵件可以使用較低的帶寬,延遲幾個小時到達目的地也沒關系
IP 規(guī)定了一些服務類型,用來定性地描述服務的質(zhì)量,舉例如下:
- 低成本:發(fā)送成本低
- 高可靠性:保證把數(shù)據(jù)可靠地送達目的地
- 最高吞吐量:一次可以接收或發(fā)送大批量的數(shù)據(jù)
- 最小延遲:傳輸數(shù)據(jù)的速度快,把數(shù)據(jù)快速送達目的地
這些服務類型還可以進行組合,例如,可以同時要求獲得高可靠性和最小延遲。服務類型存儲在 IP 數(shù)據(jù)包頭部的名為 IP_TOS 的 8 位字段中,Socket 類中提供了設置和讀取服務類型的方法
// 設置服務類型 public void setTrafficClass(int trafficClass) throws SocketException // 讀取服務類型 public int getTrafficClass() throws SocketException
服務類型用 1 字節(jié)來表示,取值范圍是 0 到 255 之間的整數(shù)。這個服務類型數(shù)據(jù)也會被復制到 TCP 數(shù)據(jù)包頭部的 8 位字段中。,在目前的網(wǎng)絡協(xié)議中,對這個表示服務類型的字節(jié)又做了進一步的細分:
- 高六位:表示 DSCP 值,即表示不同的服務類型代碼號。DSCP 允許最多有 64 種服務類型
- 低兩位:表示 ECN 值,即顯式擁塞通知信息
64 個 DSCP 值到底表示什么含義,這是由具體的網(wǎng)絡和路由器決定的。下面是比較常見的 DCSP 值:
默認服務類型:000000
加速轉(zhuǎn)發(fā)類型:101110,特點是低損耗、低延遲、低抖動
- 保證轉(zhuǎn)發(fā)類型:共 12 個取值,保證以指定速率傳送,見下表
類型 | 第1類(最低轉(zhuǎn)發(fā)優(yōu)先) | 第2類 | 第3類 | 第4類(最高轉(zhuǎn)發(fā)優(yōu)先) |
|---|---|---|---|---|
低丟包率 | 001010 | 010010 | 011010 | 100010 |
中丟包率 | 001100 | 010100 | 011100 | 100100 |
高丟包率 | 001110 | 010110 | 011110 | 100110 |
其中第 1 類有最低轉(zhuǎn)發(fā)優(yōu)先級,第 4 類有最高轉(zhuǎn)發(fā)優(yōu)先級。也就是說,當網(wǎng)絡出現(xiàn)阻塞時,第 4 類的數(shù)據(jù)包被優(yōu)先轉(zhuǎn)發(fā)。每一類又包含了 3 個取值,其中低丟包率的服務類型丟棄數(shù)據(jù)包的概率小,而高丟包率的服務類型丟棄數(shù)據(jù)包的概率大
加速轉(zhuǎn)發(fā)類型比其他服務類型有更高的優(yōu)先級,例如以下代碼使得 Socket 采用加速轉(zhuǎn)發(fā)類型來收發(fā)數(shù)據(jù):
Socket socket = new Socket("www.javathinker.net", 80);
// 0xB8 對應二進制數(shù)據(jù) 10111000
// 低兩位表示顯式擁塞通知,取值為 00
socket.setTrafficClass(0xB8);值得注意的是,DCSP 值僅僅為底層的網(wǎng)絡實現(xiàn)提供一個參考,有些底層 Socket 實現(xiàn)會忽略 DCSP 值,對它不進行任何處理
9. 設定連接時間、延遲和帶寬的相對重要性
從 JDK1.5 開始,為 Socket 類提供了一個 setPerformancePreferences() 方法
public vold setPerformancePreferences (int connectionTime, int latency, int bandwidth)
以上方法的 3 個參數(shù)表示網(wǎng)絡傳輸數(shù)據(jù)的 3 項指標:
- connectionTime:表示用最少時間建立連接
- latency:表示最小廷遲
- bandwidth:表示最高帶寬
setPerformancePreferences() 方法被用來設定這 3 項指標之間的相對要性??梢詾檫@些參數(shù)賦予任意的整數(shù)。這些整數(shù)之間的相對大小就決定了相應參數(shù)的相對重要性。例如,如果參數(shù) connectionTime 為 2,參數(shù) latency 為 1,而參數(shù) bandwidth 為 3,就表示最高帶寬最重要,其次是最少連接時間,最后是最小延遲
值得注意的是 setPerformancePreferences() 方法所做的設置僅僅為底層的網(wǎng)絡實現(xiàn)提供一個參考,有些底層 Socket 實現(xiàn)會忽略這一設置,對它不進行任何處理
到此這篇關于老生常談Java 網(wǎng)絡編程 —— Socket 詳解的文章就介紹到這了,更多相關Java Socket 詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring Cloud Ribbon實現(xiàn)客戶端負載均衡的示例
本篇文章主要介紹了Spring Cloud Ribbon實現(xiàn)客戶端負載均衡的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02
Quartz實現(xiàn)JAVA定時任務的動態(tài)配置的方法
這篇文章主要介紹了Quartz實現(xiàn)JAVA定時任務的動態(tài)配置的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07
Spring中的ThreadPoolTaskExecutor線程池使用詳解
這篇文章主要介紹了Spring中的ThreadPoolTaskExecutor線程池使用詳解,ThreadPoolTaskExecutor 是 Spring框架提供的一個線程池實現(xiàn),用于管理和執(zhí)行多線程任務,它是TaskExecutor接口的實現(xiàn),提供了在 Spring 應用程序中創(chuàng)建和配置線程池的便捷方式,需要的朋友可以參考下2024-01-01
Java Builder Pattern建造者模式詳解及實例
這篇文章主要介紹了Java Builder Pattern建造者模式詳解及實例的相關資料,需要的朋友可以參考下2017-01-01
springboot集成redis并使用redis生成全局唯一索引ID
本文主要介紹了springboot集成redis并使用redis生成全局唯一索引ID,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
Spring?Boot?配置?Hikari?數(shù)據(jù)庫連接池的操作代碼
數(shù)據(jù)庫連接池是一個提高程序與數(shù)據(jù)庫的連接的優(yōu)化,連接池它主要作用是提高性能、節(jié)省資源、控制連接數(shù)、連接管理等操作,這篇文章主要介紹了SpringBoot配置Hikari數(shù)據(jù)庫連接池,需要的朋友可以參考下2023-09-09

