生活随笔
收集整理的這篇文章主要介紹了
TCP的拥塞
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
先看一個(gè)演示
服務(wù)端代碼:
package io
.unittest
;import java
.io
.BufferedReader
;
import java
.io
.IOException
;
import java
.io
.InputStream
;
import java
.io
.InputStreamReader
;
import java
.net
.InetSocketAddress
;
import java
.net
.ServerSocket
;
import java
.net
.Socket
;
import java
.net
.SocketException
;
public class SocketIOProperties {private static final int RECEIVE_BUFFER
= 10;private static final int SO_TIMEOUT
= 0;private static final boolean REUSE_ADDR
= false;private static final int BACK_LOG
= 2; private static final boolean CLI_KEEPALIVE
= false;private static final boolean CLI_OOB
= false;private static final int CLi_REC_BUF
= 20;private static final boolean CLI_REUSE_ADDR
= false;private static final int CLI_SEND_BUF
= 20;private static final boolean CLI_LINGER
= true; private static final int CLI_LINGER_N
= 0;private static final int CLI_TIMEOUT
= 0;private static final boolean CLI_NO_DELAY
= false;public static void main(String
[] args
) {ServerSocket server
= null
;try {server
= new ServerSocket();server
.bind(new InetSocketAddress(9090), BACK_LOG
);server
.setReceiveBufferSize(RECEIVE_BUFFER
);server
.setReuseAddress(REUSE_ADDR
);server
.setSoTimeout(SO_TIMEOUT
);} catch (SocketException e
) {e
.printStackTrace();} catch (IOException e
) {e
.printStackTrace();}System
.out
.println("server up use 9090 !");try {while (true) {System
.in
.read(); Socket client
= server
.accept();System
.out
.println("client port: " + client
.getPort());client
.setKeepAlive(CLI_KEEPALIVE
);client
.setOOBInline(CLI_OOB
);client
.setReceiveBufferSize(CLi_REC_BUF
);client
.setReuseAddress(CLI_REUSE_ADDR
);client
.setSendBufferSize(CLI_SEND_BUF
);client
.setSoLinger(CLI_LINGER
, CLI_LINGER_N
);client
.setSoTimeout(CLI_TIMEOUT
);client
.setTcpNoDelay(CLI_NO_DELAY
);new Thread(() -> {try {InputStream in
= client
.getInputStream();BufferedReader reader
= new BufferedReader(new InputStreamReader(in
));char[] data
= new char[1024];while (true) {int num
= reader
.read();if (num
> 0) {System
.out
.println("client read some data is : " + num
+ " val :" + new String(data
, 0, num
));} else if (num
== 0) {System
.out
.println("client readed nothing!");continue;} else {System
.out
.println("client readed -1 ..."); System
.in
.read();break;}}} catch (IOException e
) {e
.printStackTrace();}}).start();}} catch (IOException e
) {e
.printStackTrace();} finally {try {server
.close();} catch (IOException e
) {e
.printStackTrace();}}}
}
有System.in.read(),阻塞
啟動(dòng)服務(wù)端程序,阻塞主,沒(méi)有應(yīng)用程序接收,這時(shí)候緩沖區(qū)大小是0,
這時(shí)候啟動(dòng)一個(gè)客戶(hù)端,模擬客戶(hù)端發(fā)送數(shù)據(jù),這時(shí)候緩沖區(qū)開(kāi)始漲了
不夠,繼續(xù)發(fā)到緩沖區(qū)撐爆,比如我發(fā)到1152就不漲了
那么既然不漲了,多發(fā)的數(shù)據(jù)就被丟棄了,那是丟掉了頭部的還是尾部的呢,這時(shí)候服務(wù)端回車(chē),跳過(guò)阻塞,接收數(shù)據(jù),發(fā)現(xiàn)是尾部的被丟掉了。即tcp的擁塞。
tcp怎么解決擁塞
窗口機(jī)制,還是上邊那個(gè)服務(wù)器阻塞的模型,看圖
客戶(hù)端連接的時(shí)候告訴,我有多少個(gè)窗口 win,數(shù)據(jù)包是多大 mss(1460,是ifconfig里mtu的1500減去ip和端口各占的20個(gè)字節(jié)) ,然后服務(wù)端告訴客戶(hù)端自己的win和mss,然后客戶(hù)端確認(rèn),然后連接建立,就通信。
在每次的通信數(shù)據(jù)交互過(guò)程中,客戶(hù)端和和服務(wù)端都告訴自己的窗口還有多少,如果服務(wù)端的窗口不夠用了,就阻塞住,直到數(shù)據(jù)處理完(交給應(yīng)用程序進(jìn)行下一步的處理),有空閑的窗口了就給客戶(hù)端發(fā)一個(gè)ack包通知隊(duì)列有剩余了,客戶(hù)端才繼續(xù)發(fā)包給服務(wù)端。反過(guò)來(lái)客戶(hù)端同理。就保證了tcp的包不能丟失。即擁塞控制。
總結(jié)
以上是生活随笔為你收集整理的TCP的拥塞的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。