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

Case 1[server sends data to client]

首先,我们有一个服务器,它向客户机发送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);
     }      
    } 
   }   
  } 
 }

接下来我们有一个客户端,它只读取接收到的Receive Buffer字节并打印出来,但我已经将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字节.

enter image description here

进一步确认每个数据包是25字节,判断从客户端发送的ACK窗口数据包

enter image description here

因此,在设置从客户端服务器发送的数据包的接收缓冲区大小后, case 1就完成了

Case 2[Client sends data to server]

角色颠倒了,这次我们在绑定前设置ServerSocket Receive 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判断服务器端接收的数据包后,我得到了预期的输出

enter image description here

这就完成了对客户端和服务器端接收缓冲区的理解.如果一方广播其接收缓冲区大小,另一方在每次数据包传输时只发送总意义上的数据量.

现在更难理解的部分是发送缓冲区.我对发送缓冲区的理解是

保存套接字发送的字节,只有在

因此,如果发送方的发送缓冲区=10字节,而接收方的接收缓冲区=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在接收方接收的数据包总是相同的.i、 e发送方总是发送大小为30字节的数据包.i、 e发送方总是由接收方的设置控制

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

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

推荐答案

几天前我提交了一份事故报告,已经确认为bug

Java相关问答推荐

int Array Stream System. out. print方法在打印Java8时在末尾添加% sign

Jooq外键关系

有关手动创建的包的问题

为什么一个Test的instance?& gt;在构造函数中接受非空对象?

如何解释Java中for-each循环中对Iterable的强制转换方法引用?

将Spring Boot 3.2.0升级到3.2.1后查询执行错误

在学习Spring时,通过构造函数参数0表达了不满意的依赖关系

如何使用Criteria Builder处理一对多关系中的空值?

从LineChart<;字符串、字符串和gt;中删除数据时出现特殊的ClassCastException;

A.ForEach与For(类型a:集合)

S数学.exp的相同错误保证也适用于StrictMath.exp吗?

从泛型枚举创建EnumMap

将双倍转换为百分比

Java 21内置http客户端固定运营商线程

如何使用外部函数从Java中获取C++ struct 的返回值&;内存API

原始和参数化之间的差异调用orElseGet时可选(供应商)

在JSON上获取反斜杠

如何转换Vector<;对象>;转换为int?

ANTLR 接受特殊字符,例如 .标识符或表达式中的(点)和 ,(逗号)

JavaFX 不嵌入谷歌 map html