TCP Send Buffer not doing anything

679 views Asked by At

So i am experimenting with socket buffer sizes and have created 2 test cases

Case 1[server sends data to client]

First we have a server which sends 100 bytes of data to a client

 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);
     }      
    } 
   }   
  } 
 }

And next we have an Client which simply reads the 100 bytes received and prints it but i have set the Receive Buffer size to 25 bytes. Therefore i expect the server to send 4 packets each of size 25 bytes.

 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("============");     
    } 
   } 
  }
 } 

And sure enough upon examining the packets sent from the server end using wire shark i see 4 packets[ignore malformed packets as i get no errors when receiving data on the client side and sometimes it shows malformed and sometimes no error] each with payload of size 25 bytes.

enter image description here

Further confirmation that each packet is 25 bytes is examining the ACK window packets sent from the client side

enter image description here

So case 1 is complete upon setting Receive Buffer Size from the client side server sends packets of that much size

Case 2[Client sends data to server]

The roles are reversed and this time we set the ServerSocket Receive Buffer size before binding as follows

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("============");     
      } 
     }     
    } 
   }   
  } 
 }

And the client sends data with no additional settings as follows

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);}  
  }
 }

Since the server has said it is willing to receive packets of only 10 bytes i expect the client to send 10 packets each of size 10 bytes. And sure enough upon examining the packets received on the server end using wire shark i get the expected output

enter image description here

So this completes understanding of the Receive Buffer on both the client and the server side. If one side broadcasts its receive buffer size the other side sends only that much data with each packet transmission which makes total sense.

Now comes the harder to understand part the Send Buffers. My understanding of an Send Buffer is that

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.

Thus if the sender has an send_buffer=10 bytes and if the receiver has an receive_buffer=30 bytes. The sender should still send only 10 Bytes as it is capable of holding on to only that much data which must then be Acknowledged by the receiver and then it can send the next 10 bytes and so on. But despite all my combinations of setting send buffer on the server and client side as follows

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);

The packets received on the recipient side using wire shark is always the same. i.e sender always sends packets of size 30 bytes. i.e sender is always dominated by the receiver's settings

a) Where have i gone wrong in my understanding ?

b) An very simply test case as presented above where Send Buffer actually makes an difference in both client & server side would be appreciated

1

There are 1 answers

0
Sync it On BEST ANSWER

I filed an incident report a few days ago and it has been confirmed as a bug