|
|
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
zalexakaBlazkowicz… Вот в этом примере 14921347 , по логике один из двух pump может заблокироваться, так как данные в эту сторону уже не идут. И второй pump не вызовется. Ведь поток заблокирован. Но на практике этого не происходит. … И в catch не попадает при этом? Не понял вопроса. Вышеприведенный код отлично работает. Выкидывает исключения, когда комуникация завершена и это нормально. Вопрос в том, что если клиент шлет один пакет. Сервер шлет второй и третий. Но, после 2го пакета, метод должен блокироваться на чтении из клиента. Но клиент ничего не шлет. Ждет третьего пакета с сервера. А третий пакет не передаётся, потому что поток заблокирован. Почему этого не происходит? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 12:09:49 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, Упс, тупанул вопрос действительно не в тему. BlazkowiczПочему этого не происходит? Возможно pump прокачивает пакеты по одному, других объяснений не нахожу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 12:17:34 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
BlazkowiczЕщё удивительно то что абсолютно аналогичный код на NIO API отрабатыват. Там нет available, но там и лишний read не приводит к RST. В исходниках SocketInput/OuputStream очень много проверок на isReset[Pending]. Видимо в nio проверки иначе. Но все равно без закрытия на другой стороне RST просто так возникнуть все же не может. BlazkowiczСпасибо. Не знал. А почему бы просто не закрыть клиенту соединение тогда? Или это такой способ для одной стороны сообщить другой, что она планово закрылась? Помогите понять суть RST. Ткните носом в нужный мануал, что ли. Если нужно закрывать только убедившись, что другая сторона прочитала данные, то можно сделать следующим образом. На стороне, которая хочет инициировать закрытие. Код: java 1. 2. 3. 4. А другой cтороне Код: java 1. 2. 3. 4. Или сделать специальное сообщение, которое будет говорить другой стороне, что после его получения надо бы завершить соединение. А про мануал - Сетевое программирование в Unix Стивенса. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 12:52:05 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, авторGoogle -> IO faster than NIO. И когда дело доходить до многопоточности, мы проигрываем в производительности из-за концепции thread-per-connection. Дело случая. авторКонкретику, пожалуйста. sendUrgentData() или какой ещё heartbeat? В вашем случае думается только эксепшены ловить. авторо на IO у меня не получается даже обычный протокол прокачать без защиты. Попробуйте. Там рядом ещё многопоточная реализация была. авторВозможно я не понимаю Blocking NIO. http://stackoverflow.com/questions/17615272/java-selector-is-asynchronous-or-non-blocking-architecture В качестве мультиплексора выступают селекторы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 17:45:23 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
DoSOfRedRiverИ когда дело доходить до многопоточности, мы проигрываем в производительности из-за концепции thread-per-connection. Дело случая. Зависит исключительно от того на сколько эффективно ОС управляет потоками. Переключение контекста уже совсем не дорогая операция в современных системах. DoSOfRedRiverВ вашем случае думается только эксепшены ловить. available() не выкидывает исключения. А read() выкидывает его раньше времени. Так где мне его ловить? DoSOfRedRiver Попробуйте. Там рядом ещё многопоточная реализация была. Повторяю. Вот этот гениальный код не работает для 3rd party клиента, который конектиться к моему серверу. Код: java 1. DoSOfRedRiver http://stackoverflow.com/questions/17615272/java-selector-is-asynchronous-or-non-blocking-architecture Там ни слова про configureBlocking(true) в NIO. DoSOfRedRiverВ качестве мультиплексора выступают селекторы. Холодно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 18:04:11 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowiczavailable() не выкидывает исключения. А read() выкидывает его раньше времени. Так где мне его ловить? так не выйдет? Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 19:32:04 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
забыл... Код: java 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 19:33:19 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
BlazkowiczПроблема в том что нет какого-то однозначно способа определить состояния и поступить правильно в зависимости от этого в IO. Сокет : Привязан ? Закрыт ? Подключен ? Клиент больше не пишет ? Клиент больше не читает ? Или что? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 19:59:49 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, авторТам ни слова про configureBlocking(true) в NIO. Что? Там картинка даже есть специальная, Blocking I/O называется. авторЗависит исключительно от того на сколько эффективно ОС управляет потоками. Переключение контекста уже совсем не дорогая операция в современных системах. Да. Но когда дело доходит до высоко-нагруженных приложений, почему-то предпочитают Node.js, а не Апачи всякие. авторavailable() не выкидывает исключения. А read() выкидывает его раньше времени. Так где мне его ловить? А если в код вроде if ((read = in.read(buff)) > 0) трюкача поставить и на эксепшене закрывать соединение конечным адресатом? Или вы про паузы во время передачи данных? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 20:03:14 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
BlazkowiczschwaДругая сторона нам отправила RST в ответ на нашу операцию записи. У меня на чтение. Это и оказалось большим сюрпризом.Ошибки могут возникать в любой момент. Если некто на любом участке между нами и ними уже знает, что райком закрыт и с фронта никто не вернулся, то есть всего три вариант: 1. Штатно закрыть подключение, прислав FIN-итный пакет и, возможно, соблюсти ещё какие-то формальности; 2. Тупо молчать, пока IP-стек не известит прикладуху о connection timeout; 3. Сбросить подключение прислав RST. P.S. Стек сетевых ошибок нахер никому не нужен - он всегда один и тот же. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 20:07:37 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovBlazkowiczПроблема в том что нет какого-то однозначно способа определить состояния и поступить правильно в зависимости от этого в IO. Сокет : Привязан ? Закрыт ? Подключен ? Клиент больше не пишет ? Клиент больше не читает ? Или что? Значения этих свойств одни и тоже на серверном сокете - До начала чтения пакета с клиента. - По окончании чтения пакета, до следующего чтения. - И самое обидное: после исключения connection reset вызваного чтением. То есть можно было бы поймать исключение, посмотреть свойства, что-то предпринять, а фигушки. Ни одно из этих свойств значения не меняет, когда даже в сокет нельзя ни читать, ни писать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 22:14:42 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Андрей Панфиловтак не выйдет? Я не понял чем это отличается от использования available() по поведению. На вскидку - тоже самое. Я также отхвачу исключение, при попытке чтения и тем самым "закрою" сокет на запись (клиент закроет его сам), которую мне ещё предстоит произвести. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 22:21:40 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Хм-м-м ... Надо будет поразвлекаться на досуге ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 22:22:53 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
DoSOfRedRiverавторТам ни слова про configureBlocking(true) в NIO. Что? Там картинка даже есть специальная, Blocking I/O называется. Это картинка для классического IO, а не для Blocking NIO. DoSOfRedRiverДа. Но когда дело доходит до высоко-нагруженных приложений, почему-то предпочитают Node.js, а не Апачи всякие. Сотни леммингов не могут ошбаться. DoSOfRedRiverА если в код вроде if ((read = in.read(buff)) > 0) трюкача поставить и на эксепшене закрывать соединение конечным адресатом? "трюкача поставить"? DoSOfRedRiverИли вы про паузы во время передачи данных? Нет. Я про два примера кода в начале темы. Один - мой. Не работает, потому что read выкидывает исключения и клиент закрывает сокет. Второй Андрея Панфилова - работает нормально, но нет никакого признака, чтобы выйти из цикла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 22:32:17 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, это не отличается от available, оно в дополнение - пока в буфере данные есть читаем available, если нет висим секунду на таймауте. Код: 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2013, 01:14:38 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Вот нормальный пример TCP-туннеля на блокирующем IO, один поток на сервер, один поток на клиент: http://svn.apache.org/viewvc/webservices/tcpmon/trunk/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/Relay.java?view=markup http://svn.apache.org/viewvc/webservices/tcpmon/trunk/modules/tcpmon-core/src/main/java/org/apache/ws/commons/tcpmon/TcpTunnel.java?view=markup Когда я вижу, что два соединения сидят в одном потоке, как в примере выше, у меня едва ли не кровь из глаз идет, без шуток. Вот простейший пример, когда такой подход просто катастрофически неверен. Пишете вы, значит, такой клиент-серверную игру. Написали, и вот хотите посмотреть на то, какой трафик она генерирует. Подключаете свой "Пушбэк", и начинаете смотреть. Смотрите-смотрите, вроде все в порядке. Но в какой-то момент у вас начинается "война гильдий", и сервера начинает переть дофига траффика. И вы вдруг замечаете, что клиент перестал отсылать траффик на сервер. То есть игрок видит, что происходит, но сам ничего сделать не может. Отключаете свою тулзу - все в порядке. Подключаете опять - снова игрок ничего сделать не может. А в чем проблема? Да в том, что вы никак не можете выйти из цикла, если трафика слишком много: Код: java 1. 2. 3. А что вы будете делать, если сервер устроен так, что вычитывает из клиента бинарные данные, и сериализует их в какой-нибудь условный ServerObject, но делает это до тех пор, пока не пример, скажем, 3 таких объекта, после чего перестает читать клиента, пока что-то не запишет в него? У вас опять все зависнет, теперь уже не в цикле, а внутри метода pump. Про busy-loop я уже молчу, ибо уж этот косяк должен быть всем очевиден. Поэтому я еще раз хочу заакцентировать внимание, что код, подобный этому 14927138 - это демонстрация того, как ни в коем случае нельзя организовывать TCP-туннели, особенно учитывая то, что мы тут стремимся выработать общее решение, которое будет работать для любых клиент-серверных протоколов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2013, 13:43:21 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjv, Спасибо, К.О., до вас никто не знал, что двунаправленный канал лучше обрабатывать двумя потоками, осталось только понять как это относится к: BlazkowiczWTF#1 - метод InputStream.available() бесполезен и даже сломан для сокетов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2013, 15:47:07 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Андрей Панфилов , Да точно так же, как и ваш код :-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2013, 16:11:10 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
BlazkowiczschwaБез закрытия соединения на другой стороне RST получить никак нельзя. Спасибо. Не знал. А почему бы просто не закрыть клиенту соединение тогда? Или это такой способ для одной стороны сообщить другой, что она планово закрылась? Помогите понять суть RST. Ткните носом в нужный мануал, что ли. RST - это как раз не планово а аварийно. Ключевые слова - "tcp termination sequence". Можно еще по SO_LINGER поискать, там завершение TCP-сессии тоже подробно рассматривается (лингеринг - это ручная настройка tcp termination sequence). У вас клиент делает close без shutdown (или shutdown с SO_LINGER в 0), и это большая ошибка. Правильно было бы трясти производителя, чтобы закрытие поправили, а не искать workaround. На пальцах картина примерно следующая (может быть, ошибаюсь где-то). RST - это аварийное завершение соединения. Если OS получила RST, значит, на другой стороне сокета (пары от нашего локального) больше нет ни в каком виде. Т.е. удаленная OS о "сокете" ничего не знает. Типичное использование RST - в ответ на пришедший пакет. Вот стоит у вас машина, ничего плохого не делает, а ей вдруг приходит какой-то пакет "на порт 4321 от 8.8.9.9" и якобы "в середине текущего соединения". Вот на такой пакет ваша OS пошлет RST удаленной стороне. Удаленная сторона его получит (если получит) и прекратит посылать сообщения (те же повторные отправки пакетов из-за отсутствия подтвержднеия и т.п.). Т.е. если мы получили RST, с сокетом уже ничего сделать нельзя. Нет второй стороны уже ни в каком виде (все последующие пакеты только RST в ответ и могут получить). Только открывать новый сокет. Далее. Закрытие сокета без предварительного shutdown тоже приводит к RST. Т.е. вызов "socket.close() без socket.shutdownOutput()" - это аварийное завершение, при котором, в частности, не нужно гарантировать доставку уже отправленных пакетов (да, это именно так!). Поэтому ОС посылает RST и освобождает ресурсы сразу же. Все дальнейшие входящие пакеты (как данные, так и служебные) по данному сокету получат "RST" (все структуры данных от сокета уже освобождены). Логика в этом поведении есть. Приложение решило, что "клиент уже не тот" и дальше с ним общаться смысла нет. Соответственно, данные "неправильному" клиенту доставлять тоже не нужно, поэтому можно сокет (и все структуры данных) освободить сразу же. С shutdownOuptut ситуация иная. Во-первых, вызов shutdown блокирующий и ожидает потверждения доставки всех данных от протиовоположной стороны (т.е. если что-то "не дошло", будет исключение). После shutdown и close сокет какое-то время остается в системной таблице в состоянии TIME_WAIT. В этом состоянии ОС отправляет подтверждения второй стороне о данных с нее. Нужно это, чтобы вторая (удаленная) сторона на свой socket.shutdown не получила ошибок. Пусть A - наша машина, (на ней мы сделали shutdown+close). Б - какая-то удаленная машина. Когда-то Б отправляла машине А данные. Машина А получила их, отправила подтвеждение, и это подтверждение потерялось. Т.е. с точки зрения машины А все хорошо. А с точки зрения машины Б - проблемы со связью. Поэтому Б будет какое-то время повторно посылать пакеты (retransmit). Если бы после close сокет удалялся из таблиц, машина A в ответ на retransmit послала бы RST (см. выше, это стандартный ответ если адресат не найден) и сторона Б считала бы, что данные не дошли. А так как сокет находится в TIME_WAIT, OS о нем знает и повторно отправляет подтверждение (тех данных, которые код на А уже давно обработал). Так что если shutdown отсутствует, вторая сторона мало того что получит ошибку (в любом языке!), так еще и "последние отправленные данные" могут потеряться (потому что retransmit делать уже некому). И никаких гарантий о поведении второй стороны после RST уже нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2013, 16:22:35 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
maxkarДалее. Закрытие сокета без предварительного shutdown тоже приводит к RST. Т.е. вызов "socket.close() без socket.shutdownOutput()" - это аварийное завершение, при котором, в частности, не нужно гарантировать доставку уже отправленных пакетов (да, это именно так!).Нет, это не так. Читаем JavaDoc метода close(): JavaDocCloses this socket. Any thread currently blocked in an I/O operation upon this socket will throw a SocketException. Once a socket has been closed, it is not available for further networking use (i.e. can't be reconnected or rebound). A new socket needs to be created. Closing this socket will also close the socket's InputStream and OutputStream. If this socket has an associated channel then the channel is closed as well. Более того, на первой странице я приводил пример. Вот его небольшая модификация: Код: 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. Как видите, никакого RST в виде Exception не возникает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2013, 16:30:44 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Закрытие SocketOutput/InputStream-ов при вызове socket.close() в java не имеет никакого отношения к shutdownOutput, который является вызовом shutdown с флагом SHUT_WR. Т.к. close и shutdown это разные операции. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2013, 19:33:49 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
В общем, вот как это работает, например, на Windows. Сначала читаем в MSDN статью о том, как делать gracefull shutdown сокета: http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547(v=vs.85).aspx Из этой статьи следует, что сокет можно вырубать двумя способами: shutdown() + closesocket() или WSASendDisconnect() + closesocket() . Теперь смотрим на имлепементацию дефолтного джавовского дуал-сокета: http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/windows/native/java/net/DualStackPlainSocketImpl.c Из него мы видим, что при вызове shutdown() из Java происходит вызов shutdown() в Windows. А когда мы вызываем close() из Java, то это делегируется в http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/windows/native/java/net/net_util_md.c в метод NET_SocketClose, который в свою очередь вызывает как раз таки WSASendDisconnect() + closesocket() , как и написано в WinAPI. Таким образом, Socket.close() является безопасным способом вырубать сокет. По крайней мере на Windows. Что и доказывает приведенный выше код. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 02:29:17 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvКак видите, никакого RST в виде Exception не возникает. Здесь все еще хуже. Оно банально не работает: Код: powershell 1. 2. 3. 4. 5. 6. 7. 8. 9. Я еще немного поигрался с сокетами. В общем, "по-умолчанию" socket.shutdown делает все нормально на любом языке (с точки зрения удаленной стороны). В документации я не нашел, что такое поведение гарантируется. Так что shutdown желательно делать (он еще и ошибку даст, если какие-то данные не дошли). Но если "специально постараться", отправить RST не составит большого труда: Сервер: Код: 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. Клиент: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Сервер с ключиком -ea нужно запускать (это я с вашего примера брал). Зачем стороннее приложение использует SO_LINGER? Ну не знаю. Может, оно тысячами в секунду соединения плодит и не хочет, чтобы эти сокеты висели в TIME_WAIT. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 11:08:08 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
На Windows работает нормально. Где именно вылез assert? Что на SocketExample.java:51 строке? А с SO_LINGER это некорректное рассуждение просто. Если вы его выставляете, значит для вас нормально, что другая сторона может получить RST. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 11:31:32 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvТаким образом, Socket.close() является безопасным способом вырубать сокет. По крайней мере на Windows. Что и доказывает приведенный выше код. Нет. Но в конце этой статьи написано, что нужно сделать, чтобы закрыть "безопасно" нормально. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 11:54:16 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=38417986&tid=2128468]: |
0ms |
get settings: |
19ms |
get forum list: |
21ms |
check forum access: |
6ms |
check topic access: |
6ms |
track hit: |
48ms |
get topic data: |
19ms |
get forum data: |
5ms |
get page messages: |
112ms |
get tp. blocked users: |
3ms |
| others: | 303ms |
| total: | 542ms |

| 0 / 0 |
