TCP 发送缓冲区没有做任何事情

TCP Send Buffer not doing anything

所以我正在试验套接字缓冲区大小并创建了 2 个测试用例

案例一[服务端向客户端发送数据]

首先我们有一个服务器向客户端发送 100 字节的数据

 public static void main(String[] args)throws Exception
 {
  try(ServerSocket server=new ServerSocket())
  {
   server.bind(new InetSocketAddress(InetAddress.getLocalHost(),2500));
   
   byte[] data=new byte[100];
   for(int i=0;i<data.length;i++){data[i]=(byte)i;} 
   
   while(true)
   {
    try(Socket client=server.accept())
    { 
     try(OutputStream output=client.getOutputStream())
     {
      output.write(data);
     }      
    } 
   }   
  } 
 }

接下来我们有一个客户端,它只读取接收到的 100 个字节并打印它,但我已将 Receive Buffer 大小设置为 25 个字节。因此我希望服务器发送 4 个数据包,每个数据包大小为 25 字节。

 public static void main(String[] args)throws Exception
 {
  try(Socket client=new Socket())
  {
   //receive window as 25 bytes
   client.setReceiveBufferSize(25);
   
   client.setSoLinger(true,0);
   client.bind(new InetSocketAddress("192.168.1.2",5000));  
   client.connect(new InetSocketAddress(InetAddress.getLocalHost(),2500),2000);
   
   try(InputStream input=client.getInputStream())
   {
    int length;
    byte[] data=new byte[100];
    
    while((length=input.read(data))>0)
    {
     System.out.println(Arrays.toString(Arrays.copyOfRange(data,0,length)));
     System.out.println("============");     
    } 
   } 
  }
 } 

果然在使用 wire shark 检查从服务器端发送的数据包后,我看到了 4 个数据包[忽略格式错误的数据包,因为我在客户端接收数据时没有收到任何错误,有时显示格式错误,有时显示错误]每个负载大小为 25 字节。

进一步确认每个数据包是 25 字节正在检查从客户端发送的 ACK window 数据包

所以案例 1 在客户端设置接收缓冲区大小后完成,服务器发送那么大的数据包

案例2[客户端向服务器发送数据]

角色互换,这次我们在绑定前设置ServerSocketReceive Buffer size如下

public static void main(String[] args)throws Exception
 {
  try(ServerSocket server=new ServerSocket())
  {
   //server receive window
   server.setReceiveBufferSize(10);

   server.bind(new InetSocketAddress(InetAddress.getLocalHost(),2500));
   
   int length;
   byte[] data=new byte[100];
   while(true)
   {
    try(Socket client=server.accept())
    { 
     try(InputStream input=client.getInputStream())
     {
      while((length=input.read(data))>0)
      {
       System.out.println(Arrays.toString(Arrays.copyOfRange(data,0,length)));
       System.out.println("============");     
      } 
     }     
    } 
   }   
  } 
 }

并且客户端发送的数据没有额外设置如下

public static void main(String[] args)throws Exception
 {
  try(Socket client=new Socket())
  {
   client.setReuseAddress(true);
   client.connect(new InetSocketAddress(InetAddress.getLocalHost(),2500),2000);
    
   byte[] data=new byte[100];
   for(int i=0;i<data.length;i++){data[i]=(byte)i;} 

   try(OutputStream output=client.getOutputStream()){output.write(data);}  
  }
 }

由于服务器已表示愿意接收仅 10 字节的数据包,因此我希望客户端发送 10 个数据包,每个数据包大小为 10 字节。果然在使用 wire shark 检查服务器端接收到的数据包后,我得到了预期的输出

这样就完成了对客户端和服务器端接收缓冲区的理解。如果一方广播其接收缓冲区大小,另一方在每次数据包传输时仅发送那么多数据,这完全有意义。

发送缓冲区现在更难理解了。我对发送缓冲区的理解是

Holds bytes sent by the socket and gets emptied out only after receiving an ACK from the recipient . And if it gets full it blocks the socket from sending any more data until an ACK is received.

因此,如果发送方有 send_buffer=10 个字节,如果接收方有 receive_buffer=30 个字节。发送方仍然应该只发送 10 个字节,因为它只能保留那么多数据,然后必须由接收方确认,然后它可以发送下一个 10 个字节,依此类推。但是尽管我在服务器端和客户端设置发送缓冲区的所有组合如下

1)Client sends data to server
server side=ServerSocket.setReceiveBufferSize(30);
client side=client.setSendBufferSize(10);

2)Server sends data to client
server side=serverSocket.accept().setSendBufferSize(10);
client side=client.setReceiveBufferSize(30);

接收端使用wire shark 收到的数据包总是相同的。即发件人总是发送大小为 30 字节的数据包。即发送者总是受接收者设置的支配

a) 我的理解哪里出错了?

b) 上面介绍的一个非常简单的测试用例,其中发送缓冲区实际上在客户端和服务器端都有所不同,我们将不胜感激

我几天前提交了一个事件报告,它已经被确认为 bug