Сокет, передающий файл - PullRequest
       8

Сокет, передающий файл

1 голос
/ 08 декабря 2010

У меня есть класс сервера Java, подобный следующему:

ServerSocket servsock = new ServerSocket(63456);
boolean read = false;
while (!read) {
    Socket sock = servsock.accept();
    int length = 1024;
    byte[] mybytearray = new byte[length];
    OutputStream os = sock.getOutputStream();
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
    while (true) {
    int i = bis.read(mybytearray, 0, mybytearray.length);
    if (i == 1) {
        break;
    }
    os.write(mybytearray, 0, mybytearray.length);
    os.flush();
    }
    sock.close();
    read = true;
}

`И клиент выглядит так:

Socket sock = new Socket("127.0.0.1", 63456);
byte[] mybytearray = new byte[1024];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("C:/tmp/NEWtmp.rar");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
while(bytesRead != -1 ) {
    bos.write(mybytearray, 0, bytesRead);
    bytesRead = is.read(mybytearray, 0, mybytearray.length);
}
bos.close();
sock.close();

Один вопрос: почему цикл не останавливается наконец файла?Второй вопрос: почему так медленно?

Ответы [ 2 ]

4 голосов
/ 08 декабря 2010

Это не останавливается, потому что

if (i == 1) {

в вашем источнике сервера должно быть

if (i == -1) {

Или, если вы хотите быть действительно безопасным:

if (i <= 0) {

Кроме того, вы рискуете испортить данные с помощью этой строки:

os.write(mybytearray, 0, mybytearray.length);

Вы должны изменить это на:

os.write(mybytearray, 0, i);

По производительности - переместите вызов os.flush(); за пределы while петля.Когда вы очищаете сетевой поток, вы заставляете его отправлять любые буферизованные данные в сеть.Это заставляет сетевой уровень отправлять и подтверждать 1024-байтовые полезные нагрузки TCP (конечно, большие Ethernet-нагрузки), которые, вероятно, значительно меньше, чем ваш PMTU.Вам нужно очищать только когда вы закончите отправку данных, или когда вы хотите, чтобы клиент получил буферизованные данные сейчас .Удаление вызова очистки из каждой итерации позволит сетевому буферу уровня ОС выполнять свою работу и сегментировать данные на как можно меньшее количество пакетов.

2 голосов
/ 08 декабря 2010

Второй вопрос - ваш клиент читает байты непосредственно из потока необработанных сокетов. Используйте декораторы BufferedInputStream / BufferedOutputStream, это должно повысить производительность:

Серверная сторона

BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());

Клиентская сторона

BufferedInputStream is = new BufferedInputStream(sock.getInputStream());

Необработанные потоки не буферизируются (AFAIK), поэтому при необходимости необходимо добавить буферизацию вручную.

...