Сокет TCP Java: передача данных является медленной

Инверсия Управления - то, что Вы получаете когда Ваши обратные вызовы программы, например, как gui программа.

, Например, в старом школьном меню, Вы могли бы иметь:

print "enter your name"
read name
print "enter your address"
read address
etc...
store in database

, таким образом, управление потоком взаимодействия с пользователем.

В программе GUI или somesuch, вместо этого мы говорим:

when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase

Поэтому теперь управление инвертируется... вместо компьютерного ввода данных пользователем принятия в фиксированном порядке, пользовательские элементы управления порядок, в который данные вводятся, и когда данные сохраняются в базе данных.

В основном, что-либо с циклом событий, обратными вызовами, или выполняется, триггеры попадает в эту категорию.

15
задан Bozho 1 December 2009 в 09:28
поделиться

10 ответов

Как установлен размер вашей кучи? Недавно у меня была похожая проблема с передачей больших объемов данных через сокет, и просто взглянув на JConsole , я понял, что приложение тратит большую часть своего времени на выполнение полных сборщиков мусора.

Попробуйте - Xmx1g

-1
ответ дан 1 December 2019 в 00:23
поделиться

Вам следует загрузить хороший сниффер пакетов. Лично я большой поклонник WireShark и в конечном итоге использую его каждый раз, когда занимаюсь программированием сокетов. Просто имейте в виду, что клиент и сервер должны работать в разных системах, чтобы принимать любые пакеты.

0
ответ дан 1 December 2019 в 00:23
поделиться

@Erik: использование DataXxxputStream здесь не проблема. Проблема в том, что вы отправляли данные слишком маленькими порциями. Использование буфера решило вашу проблему, потому что даже если бы вы записывали бит за битом, буфер решал бы проблему. Решение Bombe намного приятнее, универсальнее и быстрее.

1
ответ дан 1 December 2019 в 00:23
поделиться

Что нужно попробовать:

  • Установлен ли ЦП на 100% во время отправки данных? Если это так, используйте visualvm и выполните профилирование ЦП, чтобы увидеть, на что тратится время
  • Используйте SocketChannel из java.nio - это обычно быстрее, поскольку они могут легче использовать собственный ввод-вывод - конечно, это помогает, только если ваша операция Ограничение ЦП
  • Если это не связано с ЦП, что-то не так на уровне сети. Используйте анализатор пакетов, чтобы проанализировать это.
0
ответ дан 1 December 2019 в 00:23
поделиться

Вы не хотите записывать отдельные байты при передаче больших объемов данных.

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Transfer {

    public static void main(String[] args) {
        final String largeFile = "/home/dr/test.dat"; // REPLACE
        final int BUFFER_SIZE = 65536;
        new Thread(new Runnable() {
            public void run() {
                try {
                    ServerSocket serverSocket = new ServerSocket(12345);
                    Socket clientSocket = serverSocket.accept();
                    long startTime = System.currentTimeMillis();
                    byte[] buffer = new byte[BUFFER_SIZE];
                    int read;
                    int totalRead = 0;
                    InputStream clientInputStream = clientSocket.getInputStream();
                    while ((read = clientInputStream.read(buffer)) != -1) {
                        totalRead += read;
                    }
                    long endTime = System.currentTimeMillis();
                    System.out.println(totalRead + " bytes read in " + (endTime - startTime) + " ms.");
                } catch (IOException e) {
                }
            }
        }).start();
        new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(1000);
                    Socket socket = new Socket("localhost", 12345);
                    FileInputStream fileInputStream = new FileInputStream(largeFile);
                    OutputStream socketOutputStream = socket.getOutputStream();
                    long startTime = System.currentTimeMillis();
                    byte[] buffer = new byte[BUFFER_SIZE];
                    int read;
                    int readTotal = 0;
                    while ((read = fileInputStream.read(buffer)) != -1) {
                        socketOutputStream.write(buffer, 0, read);
                        readTotal += read;
                    }
                    socketOutputStream.close();
                    fileInputStream.close();
                    socket.close();
                    long endTime = System.currentTimeMillis();
                    System.out.println(readTotal + " bytes written in " + (endTime - startTime) + " ms.");
                } catch (Exception e) {
                }
            }
        }).start();
    }
}

Это копирует 1 ГиБ данных за 19 секунд на мою машину. Ключевым моментом здесь является использование InputStream.read и OutputStream. методы write , которые принимают массив байтов в качестве параметра. Размер буфера на самом деле не важен, он просто должен быть немного больше, скажем, 5. Поэкспериментируйте с BUFFER_SIZE выше, чтобы увидеть, как он влияет на скорость, но также имейте в виду, что он, вероятно, отличается для каждой машины, на которой вы работаете. эта программа включена. 64 КиБ кажутся хорошим компромиссом.

26
ответ дан 1 December 2019 в 00:23
поделиться

Как вы реализуете принимающую сторону? Пожалуйста, опубликуйте также свой код получения.

Поскольку TCP является надежным протоколом, он предпримет шаги, чтобы убедиться, что клиент может получить все данные, отправленные отправителем. Это означает, что если ваш клиент не может вовремя вытащить данные из буфера приема данных, то передающая сторона просто перестанет отправлять больше данных, пока у клиента не появится возможность прочитать все байты в приемном буфере.

Если ваш принимающая сторона читает данные по одному байту за раз, тогда ваш отправитель, вероятно, потратит много времени на ожидание очистки принимающего буфера, отсюда и длительное время передачи. Я предлагаю изменить код приема на чтение как можно большего количества байтов в каждой операции чтения . Посмотрим, решит ли это вашу проблему.

тогда ваш отправитель, вероятно, будет проводить много времени в ожидании очистки принимающего буфера, отсюда и длительное время передачи. Я предлагаю изменить код приема на чтение как можно большего количества байтов в каждой операции чтения . Посмотрим, решит ли это вашу проблему.

тогда ваш отправитель, вероятно, будет проводить много времени в ожидании очистки принимающего буфера, отсюда и длительное время передачи. Я предлагаю изменить код приема на чтение как можно большего количества байтов в каждой операции чтения . Посмотрим, решит ли это вашу проблему.

2
ответ дан 1 December 2019 в 00:23
поделиться

Можете ли вы попробовать сделать это через шлейф, он должен передать данные за секунду.

Если это займет несколько минут, с вашим приложением что-то не так. Если идет только медленная отправка данных через Интернет, возможно, у вас медленное сетевое соединение.

Я предполагаю, что у вас есть сеть со скоростью 10 Мбит / с между вашим клиентом и вашим сервером, и именно поэтому ваша передача идет медленно. В этом случае попробуйте использовать DeflatoutOutputStream и InflatorInputStream для вашего соединения.

2
ответ дан 1 December 2019 в 00:23
поделиться

Эй, я подумал, что я Я буду следить за всеми, кто был заинтересован.

Вот причудливая мораль этой истории:

НИКОГДА НЕ ИСПОЛЬЗУЙТЕ DataInputStream / DataOutputStream и сокеты !!

Если я заключу сокет в BufferedOutputStream / BufferedInputStream, жизнь прекрасна . Запись в необработанном виде - это нормально.

Но обернуть сокет в DataInputStream / DataOutputStream или даже иметь DataOutputStream (BufferedOutputStream (sock.getOutputStream ())) КРАЙНЕ МЕДЛЕННО.

Объяснение этого было бы действительно интересным. мне. Но после того, как все поменяли местами, вот что случилось. Попробуйте сами, если не верите мне.

Тем не менее, спасибо за быструю помощь.

12
ответ дан 1 December 2019 в 00:23
поделиться

Возможно, вам стоит попробовать посылать ur-данные кусками (кадрами) вместо того, чтобы записывать каждый байт отдельно. И для лучшей производительности выровняйте кадры с размером пакета TCP.

6
ответ дан 1 December 2019 в 00:23
поделиться

Использовать байтовый буфер для отправки данных

-1
ответ дан 1 December 2019 в 00:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: