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
所以我正在试验套接字缓冲区大小并创建了 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