Tôi đang cố gắng minh họa thuật toán Nagle trong một chương trình máy khách-máy chủ đơn giản. Nhưng tôi không thể hiểu rõ, hoặc làm cho nó được in rõ ràng với tôi.Java và Nagle minh họa
Trong ví dụ của tôi, máy khách chỉ tạo int từ 1 đến 1024 và gửi chúng đến máy chủ. Máy chủ chỉ chuyển đổi các int này thành chuỗi hex và gửi chúng trở lại máy khách.
Khá nhiều thứ tôi thay đổi kết thúc với cùng một kết quả. Các int được gửi và gửi lại trong các khối của 256 int .. Tôi đã thử setTcpNoDelay (true) trên cả hai mặt để xem thay đổi nhưng điều này mang lại kết quả tương tự trong bảng điều khiển của tôi. (nhưng không phải trong Wireshark, tôi thấy một sự khác biệt lớn về số lượng gói tin được gửi giữa máy chủ và máy khách) Nhưng mục tiêu của tôi là có thể nhìn thấy nó trong giao diện điều khiển, tôi đoán có một số bộ đệm của ObjectOutputStream hoặc tương tự giữ mọi thứ lên?
Khi tôi thay đổi output = new PrintWriter(client.getOutputStream(), true)
-false
(The true
hoặc false
: autoFlush
- Một boolean; nếu true
, các println
, printf
, hoặc format
phương pháp này sẽ tuôn bộ đệm đầu ra) máy chủ của tôi không đưa ra bất cứ sản lượng trở lại khách hàng nữa. Về cơ bản mục tiêu của tôi là chỉ cho đúng hoặc sai với máy chủ và/hoặc khách hàng làm đối số để đặt TcpNoDelay, khi bắt đầu, để thấy rõ sự khác biệt trong đầu vào/đầu ra trong bảng điều khiển. Tôi không chắc chắn về tất cả mọi thứ được sử dụng vì vậy bất kỳ trợ giúp để xóa này ra được hoan nghênh.
Máy chủ:
package Networks.Nagle;
import java.io.*;
import java.net.*;
import java.util.*;
public class NagleDemoServer
{
private static ServerSocket serverSocket;
private static final int PORT = 1234;
public static void main(String[] args) throws IOException
{
int received = 0;
String returned;
ObjectInputStream input = null;
PrintWriter output = null;
Socket client;
try
{
serverSocket = new ServerSocket(PORT);
System.out.println("\nServer started...");
}
catch (IOException ioEx)
{
System.out.println("\nUnable to set up port!");
System.exit(1);
}
while(true)
{
client = serverSocket.accept();
client.setTcpNoDelay(true);
System.out.println("\nNew client accepted.\n");
try
{
input = new ObjectInputStream(client.getInputStream());
output = new PrintWriter(client.getOutputStream(), true);
while(true)
{
received = input.readInt();
returned = Integer.toHexString(received);
System.out.print(" " + received);
output.println(returned.toUpperCase());
}
}
catch(EOFException eofEx)
{
output.flush();
System.out.println("\nEnd of client data.\n");
}
catch(SocketException sEx)
{
System.out.println("\nAbnormal end of client data.\n");
}
catch(IOException ioEx)
{
ioEx.printStackTrace();
}
input.close();
output.close();
client.close();
System.out.println("\nClient closed.\n");
}
}
}
Client:
package Networks.Nagle;
import java.io.*;
import java.net.*;
import java.util.*;
public class NagleDemoClient
{
private static InetAddress host;
private static final int PORT = 1234;
public static void main(String[] args)
{
Socket socket = null;
try
{
host = InetAddress.getByName("localhost");
socket = new Socket(host, PORT);
socket.setTcpNoDelay(true);
socket.setSendBufferSize(64);
System.out.println("Send Buffer: " + socket.getSendBufferSize());
System.out.println("Timeout: " + socket.getSoTimeout());
System.out.println("Nagle deactivated: " + socket.getTcpNoDelay());
}
catch(UnknownHostException uhEx)
{
System.out.println("\nHost ID not found!\n");
System.exit(1);
}
catch(SocketException sEx)
{
sEx.printStackTrace();
}
catch(IOException ioEx)
{
ioEx.printStackTrace();
}
NagleClientThread client = new NagleClientThread(socket);
NagleReceiverThread receiver = new NagleReceiverThread(socket);
client.start();
receiver.start();
try
{
client.join();
receiver.join();
socket.close();
}
catch(InterruptedException iEx)
{
iEx.printStackTrace();
}
catch(IOException ioEx)
{
ioEx.printStackTrace();
}
System.out.println("\nClient finished.");
}
}
class NagleClientThread extends Thread
{
private Socket socket;
public NagleClientThread(Socket s)
{
socket = s;
}
public void run()
{
try
{
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
for(int i = 1; i < 1025; i++)
{
output.writeInt(i);
sleep(10);
}
output.flush();
sleep(1000);
output.close();
}
catch(IOException ioEx)
{
ioEx.printStackTrace();
}
catch(InterruptedException iEx)
{
iEx.printStackTrace();
}
}
}
class NagleReceiverThread extends Thread
{
private Socket socket;
public NagleReceiverThread(Socket s)
{
socket = s;
}
public void run()
{
String response = null;
BufferedReader input = null;
try
{
input = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
try
{
while(true)
{
response = input.readLine();
System.out.print(response + " ");
}
}
catch(Exception e)
{
System.out.println("\nEnd of server data.\n");
}
input.close();
}
catch(IOException ioEx)
{
ioEx.printStackTrace();
}
}
}
Bạn có thể thử nghiệm với một người ngang hàng vừa gửi và một người khác chỉ nhận và ghi nhật ký. Nhưng dựa trên ví dụ của bạn, tôi hiểu rằng bạn muốn có một chuyến đi máy chủ cho các mục đích đo điểm chuẩn. Trong trường hợp đó, hãy để máy chủ của bạn với tcpNoDelay luôn bật và làm cho nó đọc một khối 4096 byte và trả lời nhanh chóng với bất kỳ số byte nào mà nó vừa đọc. Bạn sẽ thấy sự khác biệt bởi chỉ thay đổi tcpNoDelay trên máy khách. – fernacolo