欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

TCP的拥塞

发布时间:2024/9/30 编程问答 33 豆豆
生活随笔 收集整理的这篇文章主要介绍了 TCP的拥塞 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

先看一个演示
服务端代码:

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;/*** Author: ljf* CreatedAt: 2021/3/28 上午10:05*/ 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; // 连接的等待队列满了之后还能拍几个,linux一切皆文件嘛,意味着等着不分配文件描述符的有两个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(); // 这里阻塞住,看没有客户端的情况下,server端怎么处理连接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);// client.read //阻塞 没有 -1 0new 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 ..."); // 客户端断开,就是-1System.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(),阻塞
启动服务端程序,阻塞主,没有应用程序接收,这时候缓冲区大小是0,

这时候启动一个客户端,模拟客户端发送数据,这时候缓冲区开始涨了

不够,继续发到缓冲区撑爆,比如我发到1152就不涨了

那么既然不涨了,多发的数据就被丢弃了,那是丢掉了头部的还是尾部的呢,这时候服务端回车,跳过阻塞,接收数据,发现是尾部的被丢掉了。即tcp的拥塞。

tcp怎么解决拥塞

窗口机制,还是上边那个服务器阻塞的模型,看图


客户端连接的时候告诉,我有多少个窗口 win,数据包是多大 mss(1460,是ifconfig里mtu的1500减去ip和端口各占的20个字节) ,然后服务端告诉客户端自己的win和mss,然后客户端确认,然后连接建立,就通信。
在每次的通信数据交互过程中,客户端和和服务端都告诉自己的窗口还有多少,如果服务端的窗口不够用了,就阻塞住,直到数据处理完(交给应用程序进行下一步的处理),有空闲的窗口了就给客户端发一个ack包通知队列有剩余了,客户端才继续发包给服务端。反过来客户端同理。就保证了tcp的包不能丢失。即拥塞控制

总结

以上是生活随笔为你收集整理的TCP的拥塞的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。