2010-03-29 4 views
6

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

Trả lời

0

Bạn sẽ không thể thấy sự khác biệt bởi vì readLine() sẽ đợi cho đến khi một eol được đọc. Để xem sự khác biệt, hãy sử dụng dữ liệu nhị phân. Làm cho luồng gửi ghi khối 64 byte được phân cách bằng 10ms ngủ. Làm cho luồng đến đọc khối 1024 byte. Khi tcpNoDelay là true, luồng đến sẽ được đọc khoảng 64 byte tại mỗi thao tác đọc. Khi tcpNoDelay sai, luồng đến sẽ đọc nhiều byte hơn. Bạn có thể ghi lại số byte trung bình được đọc trong mỗi thao tác đọc, vì vậy sự khác biệt là hiển nhiên. Và cũng luôn luôn thử nghiệm bằng cách sử dụng hai máy, bởi vì hệ điều hành có thể tối ưu hóa các dòng loopback.

+0

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