Ява и Нагл иллюстрации - PullRequest
       11

Ява и Нагл иллюстрации

6 голосов
/ 29 марта 2010

Я пытаюсь проиллюстрировать алгоритм Nagle в простой клиент-серверной программе. Но я не могу понять это или сделать так, чтобы это было напечатано мне ясно.

В моем примере клиент просто генерирует целые числа от 1 до 1024 и отправляет их на сервер. Сервер просто преобразует эти int в шестнадцатеричную строку и отправляет их обратно клиенту.

Практически все, что я изменяю, приводит к тем же результатам. Int отправляются и повторно отправляются в блоках по 256 int. Я попытался установить setTcpNoDelay (true) с обеих сторон, чтобы увидеть изменения, но это дает тот же результат в моей консоли. (но не в Wireshark, я вижу большую разницу в количестве пакетов, отправляемых между сервером и клиентом) Но моя цель - увидеть это в консоли, я полагаю, что есть какой-то буфер ObjectOutputStream или что-то подобное, удерживающее все?

Когда я изменяю output = new PrintWriter(client.getOutputStream(), true) на false (true или false: autoFlush - логическое значение; если true, println, printf или format методы очистят буфер вывода) мой сервер больше не возвращает вывод клиенту.

По сути, моя цель состоит в том, чтобы просто указать true или false с сервером и / или клиентом в качестве аргумента для установки TcpNoDelay при запуске, чтобы четко видеть разницу в вводе / выводе в консоли. Я не уверен во всем, что использовалось, поэтому любая помощь, чтобы убрать это, приветствуется.

Сервер:

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

Клиент:

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

1 Ответ

0 голосов
/ 23 апреля 2011

Вы не сможете увидеть разницу, потому что readLine () будет ждать, пока eol не будет прочитан. Чтобы увидеть разницу, используйте двоичные данные. Сделайте так, чтобы блоки записи исходящего потока составляли 64 байта, разделенных 10 мс сна. Сделайте так, чтобы входящий поток читал блоки по 1024 байта. Когда tcpNoDelay имеет значение true, входящий поток будет читаться около 64 байтов при каждой операции чтения Когда tcpNoDelay имеет значение false, входящий поток будет читать намного больше байтов. Вы можете записать среднее количество прочитанных байтов в каждой операции чтения, поэтому разница очевидна. А также всегда тестируйте на двух машинах, потому что ОС может оптимизировать петлевые потоки.

...