2011-09-14 2 views
1

У меня есть домашнее задание для создания простого механизма передачи данных с помощью пары сокетов TCP/IP клиента путем перенаправления стандартного ввода-вывода. Я действительно работаю, но когда я пытаюсь передать большие файлы (скажем, ~ 5 г), скорость резко замедляется. Я использую BufferedInputStream и BufferedOutputStream, и я думаю, что, возможно, есть какая-то оптимизация, которую я могу сделать. Код для моего сервера:Увеличение скорости передачи данных на простом TCP-клиенте/сокете

private static final int BUF_SIZE = 2047; 

public static void main(String[] args) throws IOException{ 
    /* 
    * Attempt to parse command line arguments. 
    * @require args[0] is an int 
    */ 
    int port = 0; 
    try { 
     port = Integer.parseInt(args[0]); 
    } catch(NumberFormatException e) { 
     System.err.println("Port must be an integer in range 0 - 65535."); 
     System.exit(-1); 
    } 

    /* 
    * Bind server socket to specified port number and wait for request. 
    * @require port >= 0 && port <= 65535 
    */ 
    ServerSocket welcomeSocket = null; 
    welcomeSocket = new ServerSocket(port); 
    System.out.println("Now listening on port: " + port); 

    /* 
    * Accept connection from client socket. 
    */ 
    Socket connectionSocket = null; 
    connectionSocket = welcomeSocket.accept(); 
    System.out.println("Client made connection"); 

    BufferedInputStream input; 
    BufferedOutputStream output; 
    if(System.in.available() > 0) { 
     input = new BufferedInputStream(System.in, BUF_SIZE); 
     output = new BufferedOutputStream(
       connectionSocket.getOutputStream(), BUF_SIZE); 
    } else { 
     input = new BufferedInputStream(
       connectionSocket.getInputStream(), BUF_SIZE); 
     output = new BufferedOutputStream(System.out, BUF_SIZE); 
    } 

    int place; 
    while((place = input.read()) != -1) 
     output.write(place); 

    input.close(); 
    output.close(); 
    welcomeSocket.close(); 
    connectionSocket.close(); 
} 

Клиентский код по существу тот же. Я пробовал использовать разные размеры буфера, в том числе по умолчанию (не указывая размер буфера), но все они работают примерно с одинаковой скоростью. Любые указатели на то, как я могу увеличить свою производительность?

Благодарим вас за внимание!

+0

ли передача фактически замедлиться с большой файлы, или скорость становится более заметной при их передаче? Вы можете столкнуться с лимитом своего оборудования - файлы размером 5 ГБ обычно не передаются очень быстро в любой сети. –

+0

Это хороший вопрос, который я не рассматривал. Есть ли команда при использовании cmd для определения фактической скорости передачи? –

+0

Я думаю, что *, но все они работают примерно с той же скоростью *. Можете ли вы дать нам некоторое представление об относительной скорости передачи и замедлении, которое вы получаете? Это немного сложнее, чем «почему это замедляется для больших файлов?» Вероятно, это не ваш код в корне замедления. –

ответ

6
while((place = input.read()) != -1) 

Вы читаете один байт за раз из буфера. Накладные расходы на вызов этого метода в миллионы раз довольно велики.

Я хотел бы предложить чтение более одного байта в буфер с другой версии (и писать точно так же):

public int read(byte[] b, 
      int off, 
      int len) 

Пример:

byte[] myBuffer = new byte[BUF_SIZE]; 
while((place = input.read(myBuffer, 0, BUF_SIZE)) != 1) 
    output.write(myBuffer, 0, place); 
+0

Не делает ли это 'BufferedInputStream' это? –

+0

@Brendan Есть еще накладные расходы на вызов функции за байт, не так ли? Я бы подумал, что даже при буферизации копия массива будет дешевле. –

+2

Большое вам спасибо за пример! Изменяя это, чтобы использовать это read(), вместо этого фактически резко сокращалось время. Мне потребовалось около 45 секунд, чтобы перенести файл 5g. –

3

Вы читаете и отправляете байт в то время, которое неэффективно, вы должны прочитать блоки данных (размер простоя будет размером в аппаратный буфер диска). , конечно, диск должен быть вашей шеей для бутылок здесь требуется время, чтобы прочитать диск с формой 5G.

+0

Ваш ответ правильный, почему он был настолько медленным ... за исключением части в конце. Если машина не забивает диск, делая что-то еще, я гарантирую, что диск быстрее, чем сеть (если это не дискета);) Даже гигабитный Ethernet не будет быстрее, чем диск SATA. –

+0

Как я уже говорил в комментариях к другому ответу, BufferedInputStreams уже делают это. Я думаю, что проблема заключается в накладных расходах на вызов функции, а не на чтение/запись физических данных. –

+0

вы, вероятно, правы, хотя большой файл может быть фрагментирован в файловой системе и требует большого времени доступа (также доступ к структурам файлов и т. Д.). – roni

Смежные вопросы