powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / IO/NIO WTF
25 сообщений из 85, страница 2 из 4
IO/NIO WTF
    #38416170
Андрей Панфилов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Панфилов,

по факту сишная реализация сокета все что нужно для реализации хотелок у себя имеет: http://stefan.buettcher.org/cs/conn_closed.html
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416171
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowiczschwa-1 вернется только в случае, если другая сторона закрыла соединение пока мы висели на read (и все оповещения об этом успешно дошли).
Ок. А может мне кто на пальцах объяснить что такое Connection reset и как на это принято реагировать в TCP?
Другая сторона нам отправила RST в ответ на нашу операцию записи. Т.е. посчитали что наше соединение не существует - оно могло быть закрыто несколько секунд назад, процесс могли просто убить или уже вообще узел за это время успел рибутнуться и он вообще ничего не знает об этом соединении.
А что в этом случае делать это уже зависит от приложения - либо открывать новое соединение и как-то продолжить работу, либо игра окончена.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416176
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

Не очень понятно для чего вызываются проверки isInput[Output]Shutdown() в примере?
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416179
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DoSOfRedRiverСразу оговорюсь, что могу в чём-то ошибаться. Ключевые моменты лучше проверить.

В любом случае спасибо за коментарий.

DoSOfRedRiverДействительно, available возвращает количество байт, доступных для чтения. То-есть, если данные на вашу машину ещё не пришли, либо пришли не полностью, то available() вернёт 0.

Не понимаю зачем повторять то что я написал. Я это просто к тому что такое поведение нарушает контракт описаный в JavaDoc.
Без каких либо видимых причин.


DoSOfRedRiverА какой, собсна, read() вы используете?

Из кода что я привел выше, это очевидно.

DoSOfRedRiverУ меня всё нормально работало, для read() .

У меня реализация должна быть независима от протокола. С протолом HTTP всё нормально работает. С другим кастомным - нет.

DoSOfRedRiverСоветую вам использовать более удобное и эффективное чтение в массив read(byte [] arg), которое возвращает количество считанных байт.

Ваш КО.

DoSOfRedRiverИ да,
авториспользовать available для хоть какой-то эмуляции неблокируемости тоже не выйдет

Вышло по примеру Андрея Панфилова. Но осталась проблема с идентификацией завершения сессии.

DoSOfRedRiverПо поводу Connetion reset вот что пишут. Сдаётся мне, проблемы конкретно у вас.

Полезный коментарий.

DoSOfRedRiverДумается, вытекает из третьего. Всё должно нормально работать.

Мало ли что кому должно. Я описываю что конкретно и как работает на примере произвольного протокола поверх TCP. На HTTP работает. Там пакеты достаточно четко разделены.

DoSOfRedRiverИзбегайте логгирования в местах, где ошибки предсказуемы и некритичны.
Это из чего следует?

DoSOfRedRiverМожете глянуть на то, как обрабатываются ошибки в Netty, там даже лисенеры специальные есть.

Netty я потом посмотрю. Пока только хардкор. Только велосипеды.

DoSOfRedRiverСелекторы достаточно эффективная и удобная вещь, почему вы их избегаете?

Потому что я хочу получить подтверждение или опровержение того на сколько блокирующие сокеты в Java "сломаны".

DoSOfRedRiverВообще, классический IO давно устарел, он неудобен и непрактичен, потому писать лучше сразу с использованием NIO\NIO.2

В теории я знаю очень много и про IO и про NIO и про множество других страшных слов в Java мире. На практике всплывают нюансы. В NIO.2 что хорошего появилось для сокетов чтобы реализовать желаемый TCP прокси?

DoSOfRedRiverПриведу здесь пример. Как по мне, в нём отражена вся суть работы IO, кроме, разве что, многопоточного взаимодействия.

Хрен там что отражено из моих вопросов выше. На конкретном протоколе у меня проблем нет. У меня проблемы на абстракции, которая должна работать на любых протоколах.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416180
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaДругая сторона нам отправила RST в ответ на нашу операцию записи.
У меня на чтение. Это и оказалось большим сюрпризом.

schwaТ.е. посчитали что наше соединение не существует - оно могло быть закрыто несколько секунд назад, процесс могли просто убить или уже вообще узел за это время успел рибутнуться и он вообще ничего не знает об этом соединении.

Процесс открыт. Сокет открыт. Никто не бутается - все на месте.

schwaА что в этом случае делать это уже зависит от приложения - либо открывать новое соединение и как-то продолжить работу, либо игра окончена.
Это уже будет привязка к протоколу.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416182
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaНе очень понятно для чего вызываются проверки isInput[Output]Shutdown() в примере?
Та, просто осталось. Я там вообще все флаги блокирующего сокета перебрал. Ни один из них не меняет состояния ни до, ни после Connection Reset исключения.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416183
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ПанфиловsendUrgentData данные не передает а шлет флаг, правда минут что поведение зависит от ОС.
Спасибо. Попробую.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416184
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Переписал NIO на 1 поток вместо 2х, по аналогии с этим кодом 14920507 .
Всё нахрен сломалось, теперь и NIO вариант без селектора не работает :(
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416201
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DoSOfRedRiverПо поводу NIO:
Селекторы достаточно эффективная и удобная вещь, почему вы их избегаете? Вообще, классический IO давно устарел, он неудобен и непрактичен, потому писать лучше сразу с использованием NIO\NIO.2Я бы не был так категоричен. Ничего не устарело, и не устареет. Это просто два разных подхода, которые в определенных местах пересекаются, а в определенных местах нет, тем самым дополняя друг друга.
NIO с селекторами удобен, если нужен неблокирующий режим (как у автора), или если нужно обслуживать очень много соединений, когда подход "одно соединение - один поток" не справляется. Платой за использование NIO является бОльшая сложность его использования. Хотя в случае автора, когда нужно прост опрокидывать данные из одного сокета в другой, эта "добавленная сложность" будет не сильно выше, ибо не надо запариваться с размерами сообщений и выискивать их границы.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416221
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Получилось на блокирующем NIO (SocketChannel.configureBlocking(true))
вот в таком виде.

ВНИМАНИЕ. КОД НЕ РЕКОМЕДУЕТСЯ К ИСПОЛЬЗОВАНИЮ.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
class PumpTask implements Callable<Void> {
    SocketChannel inSocket;
    SocketChannel outSocket;

    public PumpTask(SocketChannel inSocket,
                    SocketChannel outSocket) {
        this.inSocket = inSocket;
        this.outSocket = outSocket;
    }

    @Override
    public Void call() throws IOException {
        ByteBuffer buff = ByteBuffer.allocate(inSocket.socket().getReceiveBufferSize());

        try {
            while (inSocket.isConnected() && outSocket.isConnected()) {
                if (!inSocket.isOpen() || !outSocket.isOpen()) Thread.sleep(1);
                pump(buff, inSocket, outSocket);
                pump(buff, outSocket, inSocket);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            inSocket.close();
            outSocket.close();
        }
        return null;
    }

    private int pump(ByteBuffer buff, SocketChannel in, SocketChannel out) throws IOException, InterruptedException {
        int read = 0;
        buff.clear();
        if ((read = in.read(buff)) > 0) {
            buff.flip();
            while (buff.hasRemaining()) {
                out.write(buff);
            }
        }
        return read;
    }
}



Дополнительные Thread.sleep() не нужны. Так как чтение блокирующее лишних циклов не возникает. Правда меня это теперь немного озадачивает. Ведь pump в одну сторону может заблокироваться и следующий уже не будет вызван. Почему вообще работает не понятно. Может один из сокетов таки сделать неблокирующим на всякий случай?
В любом случае потом перепишу на selector.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416224
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И ещё один косяк, что выход из цикла осуществляется по исключению. Этого забороть не удалось.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416238
DoSOfRedRiver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,

Я даже не могу придумать ни одного примера, в котором использование классического IO дало бы мне преимущество перед NIO.

авторНичего не устарело, и не устареет.
Точно так же можно сравнивать AWT и JavaFX. Я не хочу сказать, что эти технологии мертвы, и не нужны никому. Просто придумали уже вещи удобней и красивей.

Blazkowicz,

авторВышло по примеру Андрея Панфилова.
Дак в примере выходит по соединению на поток, не? Тогда вообще не понимаю, какие могут быть проблемы.

авторНо осталась проблема с идентификацией завершения сессии.
По-моему самым эффективным способ будет посылать heartbeat, который проверяет жив ли клиент. Да и других вариантов не могу найти, потому как клиент может просто шутдаунуться.

авторПотому что я хочу получить подтверждение или опровержение того на сколько блокирующие сокеты в Java "сломаны".
Сломаны? Как они могут быть "сломаны"? Вроде куча народу юзает блокинг-ио, никто не жаловался особо.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416302
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DoSOfRedRiverДак в примере выходит по соединению на поток, не? Тогда вообще не понимаю, какие могут быть проблемы.Два блокирующих сокета на поток. Потому у автора и проблемы.

DoSOfRedRiverПо-моему самым эффективным способ будет посылать heartbeat, который проверяет жив ли клиент. Да и других вариантов не могу найти, потому как клиент может просто шутдаунуться.Так и есть. Состояние, когда клиент подох, а сервер этого не увидел (или наоборот) - называется half-open socket. И хартбиты позволяют успешно детектировать эту ситуацию. Но автору нужно сделать прокси, вклиниться между клиентом и сервером, и просто форвардить данные из одной стороны в другую. Так что хартбиты тут не помогут.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416399
maxkar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowiczметод InputStream.available() бесполезен и даже сломан для сокетов.
Он всегда был бесполезен для клиентского кода. Из разумных его применений я вижу только его использование в различных Buffered* обертках. Там обертка может увидеть, что данных много, и реалоцировать буфер.

BlazkowiczЧитаем JavaDoc
Returns:an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking or 0 when it reaches the end of the input stream.

На сокетах available будет изначально возвращать 0, если узел с другой стороны ничего не отправляет. Но это ещё не значит что поток завершен.

Вы javadoc неправильно понимаете. Javadoc и не обещает, что 0 - это только конец потока. У вас возвращается "number of bytes that can be read without blocking". Ну нет там байтов, чтобы читать. И ноль - вполне корректное значение для первой половины (даже когда конец потока еще не достигнут). Причем "0 в случае конце файла" - это всего лишь уточнение. Оно вполне следует из первой половины контракта. По той же самой причине - "из потока можно прочитать не более 0 байт без блокирования". Разница с read есть, но для данного места оно вполне оправдана. Файловые потоки тоже могут возвращать 0 раньше достижения конца файла.

BlazkowiczWTF#2 Дальше хуже. read(), который должен вернуть -1 по окончании чтения тоже никогда -1 не возвращает. В общем случае никакого начала и конца у InputStream для сокетов нет. А использовать available для хоть какой-то эмуляции неблокируемости тоже не выйдет.

Начало есть. Если сделать Socket.shutdownOutput на стороне клиента, то у сервера и конец потока будет. А если не делать, то и конца не будет. Что логично - по одному соединению можно обмениваться многими соединениями. И даже тот же браузер может не закрывать сокет (поэтому -1 и не будет), а использовать его для послдеюущих запросов.

BlazkowiczНачал тестировать на боевом приложении, WTF#3
Клиент отправляет пакет данных. Он прочитан, перенаправлен на другой сервер. После этого мой серверный сокет снова пытается сделать read(). В теории он должен либо заблокироваться, либо вернуть -1.
На практике чтение выкидывает исключение Connection reset! Но это пол беды. Помимо этого клиентская сторона закрывает свой сокет и на запись. Т.е. отклик сервера записать проигнорировав reset уже нельзя.

Код смотреть надо. Вы там никакой из сокетных потоков или оберток над ними вручную не закрываете? Закрытие любого из них будет приводить к закрытию сокета. Или на сервере вместо shutdown сокету делается close. Для надежной доставки данных нельзя "просто закрыть потоки и сокет". Сначала нужно сделать shutdown (один или два, в зависимости от того, что делаете). И только потом закрывать сокет. В случае исключений shutdown делать уже не имеет смысла.

BlazkowiczWTF#4 - не смотря на connection reset и невозможность дальнейшей работы с клиентом со стороны сервера, никакие флаги у сокета не меняются. Всякие connected, closed и пр. находятся в том же состоянии что и в начале работы. Т.е. спросит клиента с сервера живо ли тот ещё никакой возможности не видно.

Это плохая документация. "isConnected" вооще обозначает, что "соединение хоть когда-то было установлено (смотрите документацию)", а не "сейчас соединение установлено". При использовании большей части конструкторов isConnected всегда будет true. С isClosed ситуация чем-то похожая. Этот флаг всего лишь обозначает, что "сокет был закрыт вызовом метода close или закрытием одного из сокетных потоков". Он не обозначает, что клиент на другой стороне закрыл соединение и т.п. Да, завершение соединения с другой стороны/ошибки/сброс соединения сокет не закрывают. Его все равно нужно закрыть вручную.

BlazkowiczWTF#5 - я вообще смотрю на разные проекты и вижу что постоянные исключения в TCP на Java это вообще штатные ситуации. Имеет ли смысл избегать логирования stacktrace для повышения производительности? Ведь если разворачивать stacktrace на каждый пук при многочисленых соединениях и отсоединениях клиентов, то провал в производительности обеспечен.

Да, достаточно штатная. Логировать ли - зависит от приложения и нагрузки. Во многих случаях протокол имеет явные начало/конец (с соответствующими shutdown и т.п.), поэтому исключения при допустимой нагрузке логировать стоит (мало ли что там). А вот если вы какой-нибудь streaming server пишете, где клиент в какой-то момент просто исчезает (приложение закрыли), там можно и не логировать ничего.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416401
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczschwaДругая сторона нам отправила RST в ответ на нашу операцию записи.
У меня на чтение. Это и оказалось большим сюрпризом.

schwaТ.е. посчитали что наше соединение не существует - оно могло быть закрыто несколько секунд назад, процесс могли просто убить или уже вообще узел за это время успел рибутнуться и он вообще ничего не знает об этом соединении.

Процесс открыт. Сокет открыт. Никто не бутается - все на месте.

Операция записи завершается, когда переданные данные были скопированы в буфер отправки. На следующей операции записи/чтения будет получен connection reset, если за это время произошел обрыв соединения и эта сторона соединения об этом узнала.
Без закрытия соединения на другой стороне RST получить никак нельзя.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416445
maxkar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В спойлере пример. Проверял на www.apache.org порт 80. Никаких исключений. Никаких проблем с сокетами. Радостно общается с браузером потоков в 10 и при этом с HTTP keep-alive (видно по логам и сообщениям о закрытии сокетов). Соединения могут закрываться и при неактивности (т.е. конец файла определяется с обеих сторон), тоже видно по сообщениям.

Если делать совсем правильно, читалку и писалку тоже нужно разделить на два потока (на три потока, в примере две записи). Читалка складывает данные в буфер. Если данных в буфере слишком много, закрывает сокет со второй стороны и свой сокет (генерируя попутно кучу исключений в духе SocketClosedException, ConnectionReset и т.п.).


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
import java.io.*;
import java.net.*;

public class Proxy {

  private static class Copier implements Runnable {
    final OutputStream logStream;
    final OutputStream copyStream;
    final InputStream is;
    final Socket osock;

    Copier(OutputStream logStream, OutputStream copyStream, 
        InputStream is, Socket osock) {
      this.logStream = logStream;
      this.copyStream = copyStream;
      this.is = is;
      this.osock = osock;
    }

    @Override
    public void run() {
      final byte[] buffer = new byte[65536];
      try {
        try {
          while (true) {
            final int readed = is.read(buffer);
            if (readed < 0) {
              osock.shutdownOutput();
              return;
            }

            logStream.write(buffer, 0, readed);
            copyStream.write(buffer, 0, readed);
          }
        } finally {
          logStream.close();
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  private static class Killer implements Runnable {
    final Thread t1;
    final Thread t2;
    final Socket s1;
    final Socket s2;

    Killer(Thread t1, Thread t2, Socket s1, Socket s2) {
      this.t1 = t1;
      this.t2 = t2;
      this.s1 = s1;
      this.s2 = s2;
    }

    @Override
    public void run() {
      try {
        try {
          t1.join();
          t2.join();
          System.out.println("Killing the sockets!");
        } finally {
          try {
            s1.close();
          } finally {
            s2.close();
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  public static void main(String[] args) throws Exception {
    final ServerSocket ss = new ServerSocket(8888);
    int log = 0;
    while (true) {
      final Socket cconn =  ss.accept();
      final Socket sconn = new Socket(args[0], Integer.parseInt(args[1]));
      
      final Thread t1 = new Thread(new Copier(new FileOutputStream("c2s" + log), 
            sconn.getOutputStream(), cconn.getInputStream(), sconn));
      final Thread t2 = new Thread(new Copier(new FileOutputStream("s2c" + log), 
            cconn.getOutputStream(), sconn.getInputStream(), cconn));
      t1.start();
      t2.start();
      new Thread(new Killer(t1, t2, cconn, sconn)).start();
      log += 1;
    }
  }
}


...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416487
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DoSOfRedRiverЯ даже не могу придумать ни одного примера, в котором использование классического IO дало бы мне преимущество перед NIO.

Google -> IO faster than NIO.


DoSOfRedRiverТочно так же можно сравнивать AWT и JavaFX. Я не хочу сказать, что эти технологии мертвы, и не нужны никому. Просто придумали уже вещи удобней и красивей.
Аналогия не уместна.

DoSOfRedRiverДак в примере выходит по соединению на поток, не? Тогда вообще не понимаю, какие могут быть проблемы.
Проблемы я объяснил в первом посте и по вашей просьбе привел текст кода, который эти проблемы вскрывает.

DoSOfRedRiverПо-моему самым эффективным способ будет посылать heartbeat, который проверяет жив ли клиент. Да и других вариантов не могу найти, потому как клиент может просто шутдаунуться.
Конкретику, пожалуйста. sendUrgentData() или какой ещё heartbeat?

DoSOfRedRiverСломаны? Как они могут быть "сломаны"? Вроде куча народу юзает блокинг-ио, никто не жаловался особо.
IO работает когда протокол заранее оговорен. У меня нет протокола. Мне нужно прокачивать любые данные любых протоколов поверх TCP. Конечно, если протокол защищен он атаки man-in-the-middle, то работать никакой вариант не будет.
Но на IO у меня не получается даже обычный протокол прокачать без защиты. Почему? - описал в первом посте и привел код.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416490
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvДва блокирующих сокета на поток. Потому у автора и проблемы.
У меня и по сокету на поток проблемы и два сокета на поток тоже проблемы.

cdtyjvТак и есть. Состояние, когда клиент подох, а сервер этого не увидел (или наоборот) - называется half-open socket. И хартбиты позволяют успешно детектировать эту ситуацию. Но автору нужно сделать прокси, вклиниться между клиентом и сервером, и просто форвардить данные из одной стороны в другую. Так что хартбиты тут не помогут.
А на sendUrgentData()?
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416500
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczУ меня и по сокету на поток проблемы и два сокета на поток тоже проблемы.А вы код "сокет-на-поток" выкладывали? А то я уже запутался, где что.

BlazkowiczА на sendUrgentData()?В общем случае sendUrgentData() не работает. Что бы спокойно ее использовать, необходимо быть уверенным, что принимающая сторона знает, как с этой самой urgent data быть. В противном случае вы по сути будете отсылать на другую стороны какие-то левые байты, который запорят протокол, и приведут к непредсказуемым последствиям.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416501
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maxkarВы javadoc неправильно понимаете. Javadoc и не обещает, что 0 - это только конец потока. У вас возвращается "number of bytes that can be read without blocking". Ну нет там байтов, чтобы читать. И ноль - вполне корректное значение для первой половины (даже когда конец потока еще не достигнут). Причем "0 в случае конце файла" - это всего лишь уточнение. Оно вполне следует из первой половины контракта. По той же самой причине - "из потока можно прочитать не более 0 байт без блокирования". Разница с read есть, но для данного места оно вполне оправдана. Файловые потоки тоже могут возвращать 0 раньше достижения конца файла.
Спасибо! Теперь понял основную ошибку.

maxkarНачало есть. Если сделать Socket.shutdownOutput на стороне клиента, то у сервера и конец потока будет. А если не делать, то и конца не будет. Что логично - по одному соединению можно обмениваться многими соединениями. И даже тот же браузер может не закрывать сокет (поэтому -1 и не будет), а использовать его для послдеюущих запросов.
У меня 3rd party клиент. Он шлет reset вместо всего остального.

maxkarКод смотреть надо.

14920906

maxkarВы там никакой из сокетных потоков или оберток над ними вручную не закрываете? Закрытие любого из них будет приводить к закрытию сокета. Или на сервере вместо shutdown сокету делается close. Для надежной доставки данных нельзя "просто закрыть потоки и сокет". Сначала нужно сделать shutdown (один или два, в зависимости от того, что делаете). И только потом закрывать сокет. В случае исключений shutdown делать уже не имеет смысла.
Проблема ни в shutdown/close. Проблема в том что когда сервер делает read с клиентского сокета, вылетает Connection Reset и предотвратить это можно только через available().


maxkarЭто плохая документация. "isConnected" вооще обозначает, что "соединение хоть когда-то было установлено (смотрите документацию)", а не "сейчас соединение установлено". При использовании большей части конструкторов isConnected всегда будет true. С isClosed ситуация чем-то похожая. Этот флаг всего лишь обозначает, что "сокет был закрыт вызовом метода close или закрытием одного из сокетных потоков". Он не обозначает, что клиент на другой стороне закрыл соединение и т.п. Да, завершение соединения с другой стороны/ошибки/сброс соединения сокет не закрывают. Его все равно нужно закрыть вручную.

Клиент послал Reset и у клиентского сокета на сервере никакие флаги вообще не поменялись. Это и смущает.

maxkarДа, достаточно штатная. Логировать ли - зависит от приложения и нагрузки. Во многих случаях протокол имеет явные начало/конец (с соответствующими shutdown и т.п.), поэтому исключения при допустимой нагрузке логировать стоит (мало ли что там). А вот если вы какой-нибудь streaming server пишете, где клиент в какой-то момент просто исчезает (приложение закрыли), там можно и не логировать ничего.
Мне нужно решение не привязаное к конкретным протоколам. Если я использую available(), то я не могу выйти из цикла. И клиентский и серверный сокет живут себе даже после окончания сессии обмена данными. Если я не использую available(), то я выхватываю исключение на методе read() и дальнейшая работа с этим сокетом не возможна. Может надо было ещё и со стороны сервера reset() вызвать чтобы обновить сокет? Не очевидно как-то.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416507
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaОперация записи завершается, когда переданные данные были скопированы в буфер отправки. На следующей операции записи/чтения будет получен connection reset, если за это время произошел обрыв соединения и эта сторона соединения об этом узнала.
Вот такой вот хитрый протокол попался. Если делать read больше нужного - отгребаешь RST. Если предотвратить RST через available(), то не происходит выхода из цикла.
Ещё удивительно то что абсолютно аналогичный код на NIO API отрабатыват. Там нет available, но там и лишний read не приводит к RST.

schwaБез закрытия соединения на другой стороне RST получить никак нельзя.
Спасибо. Не знал. А почему бы просто не закрыть клиенту соединение тогда? Или это такой способ для одной стороны сообщить другой, что она планово закрылась? Помогите понять суть RST. Ткните носом в нужный мануал, что ли.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416515
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maxkarВ спойлере пример. Проверял на www.apache.org порт 80. Никаких исключений. Никаких проблем с сокетами. Радостно общается с браузером потоков в 10 и при этом с HTTP keep-alive (видно по логам и сообщениям о закрытии сокетов). Соединения могут закрываться и при неактивности (т.е. конец файла определяется с обеих сторон), тоже видно по сообщениям.

На HTTP у меня тоже всё работало без проблем. На другом TCP протоколе метод read из вашего примера выкинет Exception до окончания сессии обмена данными. При этом сокет ещё и закрывается, так что в него нельзя записать отклик.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416522
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvА вы код "сокет-на-поток" выкладывали? А то я уже запутался, где что.
Вот мой первоначальный код.
14920906
Запускается два потока. Один работает с клиентским сокетом. Второй с серверным.
(третий сидит на ServerSocket.accept(), но это не важно)


cdtyjvА на sendUrgentData()?В общем случае sendUrgentData() не работает. Что бы спокойно ее использовать, необходимо быть уверенным, что принимающая сторона знает, как с этой самой urgent data быть. В противном случае вы по сути будете отсылать на другую стороны какие-то левые байты, который запорят протокол, и приведут к непредсказуемым последствиям.[/quot]
Понял. Спасибо.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416531
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем большое спасибо за обсуждение. Возник ещё вопрос по NIO.
Вот в этом примере 14921347 , по логике один из двух pump может заблокироваться, так как данные в эту сторону уже не идут.
И второй pump не вызовется. Ведь поток заблокирован.
Но на практике этого не происходит. Кто-нибудь может объяснить почему? Или мне просто повезло с протоколом? Вечером залогирую более детально. Но методы вызываются строго по очереди. Возможно в каких-то случаях они качают 0 байт, но при этом лишний вызов на TCP не происходит (смотрел снифером)
Возможно я не понимаю Blocking NIO.
Надо, наверное, ещё свои собственные клиент-сервер написать для теста хитрых протоколов.
...
Рейтинг: 0 / 0
IO/NIO WTF
    #38416603
zalexaka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz…
Вот в этом примере 14921347 , по логике один из двух pump может заблокироваться, так как данные в эту сторону уже не идут.
И второй pump не вызовется. Ведь поток заблокирован.
Но на практике этого не происходит.

И в catch не попадает при этом?
...
Рейтинг: 0 / 0
25 сообщений из 85, страница 2 из 4
Форумы / Java [игнор отключен] [закрыт для гостей] / IO/NIO WTF
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]