|
|
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Понадобилось написать TCP "прокси", чем-то аналогичный вот этой тулзе http://ws.apache.org/tcpmon/tcpmontutorial.html С сокетами знаком исключительно по форумам, поэтому решил заполнить этот пробел ограничившись для начала Java API. В качестве тестового варианта написал простейший насос данных в одну и другую сторону на plain IO. WTF#1 - метод InputStream.available() бесполезен и даже сломан для сокетов. Читаем 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, если узел с другой стороны ничего не отправляет. Но это ещё не значит что поток завершен. WTF#2 Дальше хуже. read(), который должен вернуть -1 по окончании чтения тоже никогда -1 не возвращает. В общем случае никакого начала и конца у InputStream для сокетов нет. А использовать available для хоть какой-то эмуляции неблокируемости тоже не выйдет. Кое как заборол. Работает на браузере. Начал тестировать на боевом приложении, WTF#3 Клиент отправляет пакет данных. Он прочитан, перенаправлен на другой сервер. После этого мой серверный сокет снова пытается сделать read(). В теории он должен либо заблокироваться, либо вернуть -1. На практике чтение выкидывает исключение Connection reset! Но это пол беды. Помимо этого клиентская сторона закрывает свой сокет и на запись. Т.е. отклик сервера записать проигнорировав reset уже нельзя. WTF#4 - не смотря на connection reset и невозможность дальнейшей работы с клиентом со стороны сервера, никакие флаги у сокета не меняются. Всякие connected, closed и пр. находятся в том же состоянии что и в начале работы. Т.е. спросит клиента с сервера живо ли тот ещё никакой возможности не видно. Психанул. Переписал всё на NIO без селекторов. Т.е. тот же многопоточный подход что и в IO, только через NIO API. И, о чудо! Работает. Причем независимо от параметра configureBlocking(). Никаких проблем с чтением после первого пакета почему-то нет. Всё до окончания сессии обмена пакетами работает более менее. WTF#5 - я вообще смотрю на разные проекты и вижу что постоянные исключения в TCP на Java это вообще штатные ситуации. Имеет ли смысл избегать логирования stacktrace для повышения производительности? Ведь если разворачивать stacktrace на каждый пук при многочисленых соединениях и отсоединениях клиентов, то провал в производительности обеспечен. И напоследок вопрос про NIO - как лучше всего избегать холостых циклов чтения, когда данные ещё не отправленый второй стороной. Они почему-то возникают даже при configureBlocking(true). Перейти исключительно на селекторы? Варианты с Thread.sleep(n) как-то не улыбаются. Комментарии и нравоучения приветствуются. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 17:20:43 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Можно селектор использовать http://tutorials.jenkov.com/java-nio/selectors.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 17:54:49 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
ЛагманМожно селектор использовать http://tutorials.jenkov.com/java-nio/selectors.html Прочитано несколько раз. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 17:59:29 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, относительно 1-3. На транспортном вы не можете знать сколько байт должен в итоге передать клиент, потому что это определяется протоколом приложения, поэтому для сокета у вас фактически только три состояния: в буфере есть данные, их нужно считать и отправить дальше, в буфере нет данных - нужно ждать когда появятся, сокет закрыт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 18:03:07 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Андрей ПанфиловНа транспортном вы не можете знать сколько байт должен в итоге передать клиент, потому что это определяется протоколом приложения Правильно. Если можно привязаться к протоколу, то всё становится просто. Андрей ПанфиловПоэтому для сокета у вас фактически только три состояния: в буфере есть данные, их нужно считать и отправить дальше, в буфере нет данных - нужно ждать когда появятся, сокет закрыт. Именно. Проблема в том что нет какого-то однозначно способа определить состояния и поступить правильно в зависимости от этого в IO. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 18:06:13 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
BlazkowiczПроблема в том что нет какого-то однозначно способа определить состояния и поступить правильно в зависимости от этого в IO.Не понял проблемы.. д.б. что-то в духе: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. по вкусу вставить sleep, т.е. на одно проксируемое соединение уходит один поток ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 18:14:18 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Спасибо за пример! Попробую на досуге в таком ключе. На первый взгляд, действительно, можно избежать вышеуказаных проблем таким способом. Я просто сходу в разных потоках это делал. Для NIO понял что лучше объединить. Для IO, вижу, вообще без объединения не обойтись. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 18:18:19 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Для файлового ввода-вывода имплементация IO должна импортировать в себя пакеты NIO. Как там с сокетами - ХЗ но странно всё это. Насчёт переписывания. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 19:31:19 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Не очень понял, что у вас за проблемы с 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. Но это "Java из Java". Я легко допускаю, что клиенты/сервера, с которыми вы взаимодействуете могут рвать соединения некорректно. В любом случае, для вычитки никаких проблем быть не должно. Метод available() имеет лишь ограниченную применимость, и скедулить потоки, полагаясь на него, разумеется, нельзя. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 20:02:25 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
По NIO - да, лучше всего сидеть на селекторах. Один тред слушает slector.select(), потом диспатчит это в другие треды - это типичный паттерн для этого дела. Вот очень хороший туториал по NIO: http://rox-xmlrpc.sourceforge.net/niotut/ P.S.: Если често, не очень понял, как NIO может быть без селекторов ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 20:08:06 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvP.S.: Если често, не очень понял, как NIO может быть без селекторов Тот же IO, только проще, и без блокировки. http://tutorials.jenkov.com/java-nio/socket-channel.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 20:11:49 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvНе очень понял, что у вас за проблемы с available(). Вот пример, в котором все абсолютно четко работает: Я не знаю размеров пакетов. И не могу на них полагаться. Я полагался на то что метод read заблокируется если что или вернет -1. А ещё я к тому что SocketInputStream нарушает контракт InputStream. cdtyjvЯ легко допускаю, что клиенты/сервера, с которыми вы взаимодействуете могут рвать соединения некорректно. Так и есть. cdtyjvВ любом случае, для вычитки никаких проблем быть не должно. Вот чтение меня больше всего и озадачило. Как только я пытаюсь в IO читать больше чем длина пакета, то получаю исключение Connection reset, вместо ожидаемой блокировки или -1. И что самое удивительно что в блокирующем режиме через NIO такого не происходит. Я понимаю что частично это и косяк стороннего клиентского сокета. Но как-то слишком много сюрпризов по сравнению с ожиданиями из JavaDoc. cdtyjvМетод available() имеет лишь ограниченную применимость, и скедулить потоки, полагаясь на него, разумеется, нельзя. Скедулить потоки я на нем не собирался. Я думал как бы его вообще применить к моей задаче. Но вот до такого 14920507 не додумался, так как всё делал в 2х потоках а не в одном. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 20:20:18 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, Приведите пример Вашего кода работы с IO. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 20:28:57 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
DoSOfRedRiverBlazkowicz, Приведите пример Вашего кода работы с IO. Две такие асинхронные таски запускаются с каждой стороны. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 20:34:17 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
BlazkowiczСкедулить потоки я на нем не собирался. Я думал как бы его вообще применить к моей задаче. Но вот до такого 14920507 не додумался, так как всё делал в 2х потоках а не в одном.Настоятельно НЕ рекомендую использовать этот код, ибо это что-то сродни busy loop в многопоточном программировании. Если вы не хотите блокироваться, то смело берите селектор, и вперед. Там есть нормальный Selector.select(), с которым никаких Thread.sleep() и прочего *** не надо делать. Тупо один поток сидит на селекторе. Как только с сокетом происходит какое-то событие - он просыпается, и говорит вам, что это было. А вы в зависимости от этого переадресуете работу в другой поток. В общем, по ссылке, что я привел выше это очень хорошо расписано. Мне в свое время именно этот материал поставил голову на место по части NIO. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:05:52 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
авторДальше хуже. read(), который должен вернуть -1 по окончании чтения тоже никогда -1 не возвращает. -1 вернется только в случае, если другая сторона закрыла соединение пока мы висели на read (и все оповещения об этом успешно дошли). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:17:43 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Андрей Панфилов, Спасибо огромное! Работает в лучшем виде! Код на много проще и ещё другуя бага выловилась после рефакторинга. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:19:09 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvНастоятельно НЕ рекомендую использовать этот код, ибо это что-то сродни busy loop в многопоточном программировании. Какой именно? cdtyjvЕсли вы не хотите блокироваться, то смело берите селектор, и вперед. Это я знаю. Я планировал блокироваться в первой итерации. cdtyjvТам есть нормальный Selector.select(), с которым никаких Thread.sleep() и прочего *** не надо делать. Я в курсе. Мануал прочитан. Примеры прочитаны. Thread.sleep() не планировал использовать в продакшне. Собственно это всё никак не отвечает на мои вопросы выше. Было интересно как сделать через IO. И почему именно так. cdtyjvТупо один поток сидит на селекторе. Как только с сокетом происходит какое-то событие - он просыпается, и говорит вам, что это было. А вы в зависимости от этого переадресуете работу в другой поток. На словах я это сам могу рассказывать кому угодно. :) Так и сделаю когда до нагрузки дойдёт. cdtyjvВ общем, по ссылке, что я привел выше это очень хорошо расписано. Мне в свое время именно этот материал поставил голову на место по части NIO. Спасибо прочту. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:24:30 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
schwa-1 вернется только в случае, если другая сторона закрыла соединение пока мы висели на read (и все оповещения об этом успешно дошли). Ок. А может мне кто на пальцах объяснить что такое Connection reset и как на это принято реагировать в TCP? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:25:17 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Андрей Панфилов Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Блин. Рано радовался. Сессия обмена данных протекла успешно. Это супер. Но! Вылез косяк. После сессии оба сокета открыты. Соединение активно. Я не могу выйти из этого цикла! Ведь я не делаю блокирующего read(), который бы мог вернуть -1 или выкинуть исключение. Так что IO вариант, похоже, в моём случае окончательно сломан. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:30:14 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, тут беда с isClosed() ровно как и с вашим inSocket.isInputShutdown() - чтобы получить на них true, нужно закрытие сокета инициировать в JVM. По факту жавская реализация сокета предполагает, что чтобы убедиться что сокет закрыт, нужно либо в него что-то записать (тут мы протокол ломаем), либо прочитать (тут зависнем на таймауте), как вариант можно вместо isClosed() ловить эксепшн на sendUrgentData() ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:39:29 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Андрей Панфиловлибо прочитать (тут зависнем на таймауте) Или отхватим исключение ещё до окончания записи. Андрей Панфиловкак вариант можно вместо isClosed() ловить эксепшн на sendUrgentData() Не вижу разницы с write. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:43:57 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, Сразу оговорюсь, что могу в чём-то ошибаться. Ключевые моменты лучше проверить. Итак, WTF#1 Действительно, available возвращает количество байт, доступных для чтения. То-есть, если данные на вашу машину ещё не пришли, либо пришли не полностью, то available() вернёт 0. WTF#2 А какой, собсна, read() вы используете? У меня всё нормально работало, для read() . Советую вам использовать более удобное и эффективное чтение в массив read(byte [] arg), которое возвращает количество считанных байт. И да, авториспользовать available для хоть какой-то эмуляции неблокируемости тоже не выйдет WTF#3 По поводу Connetion reset вот что пишут. Сдаётся мне, проблемы конкретно у вас. WTF#4 Думается, вытекает из третьего. Всё должно нормально работать. WTF#5 Избегайте логгирования в местах, где ошибки предсказуемы и некритичны. Можете глянуть на то, как обрабатываются ошибки в Netty, там даже лисенеры специальные есть. По поводу NIO: Селекторы достаточно эффективная и удобная вещь, почему вы их избегаете? Вообще, классический IO давно устарел, он неудобен и непрактичен, потому писать лучше сразу с использованием NIO\NIO.2 Приведу здесь пример. Как по мне, в нём отражена вся суть работы IO, кроме, разве что, многопоточного взаимодействия. Пример не мой, кстати. Код: 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. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:44:24 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, sendUrgentData данные не передает а шлет флаг, правда минут что поведение зависит от ОС. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:48:59 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
DoSOfRedRiver, Алсо для многопоточной обработки внешних соединений рекомендую асинхронное неблокироющее IO с NIO.2 и шаблон Proactor. Ну это если вам надо высокоэффективное приложение, по типу вэб-сервер. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 21:49:34 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Андрей Панфилов, по факту сишная реализация сокета все что нужно для реализации хотелок у себя имеет: http://stefan.buettcher.org/cs/conn_closed.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:03:37 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowiczschwa-1 вернется только в случае, если другая сторона закрыла соединение пока мы висели на read (и все оповещения об этом успешно дошли). Ок. А может мне кто на пальцах объяснить что такое Connection reset и как на это принято реагировать в TCP? Другая сторона нам отправила RST в ответ на нашу операцию записи. Т.е. посчитали что наше соединение не существует - оно могло быть закрыто несколько секунд назад, процесс могли просто убить или уже вообще узел за это время успел рибутнуться и он вообще ничего не знает об этом соединении. А что в этом случае делать это уже зависит от приложения - либо открывать новое соединение и как-то продолжить работу, либо игра окончена. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:05:28 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, Не очень понятно для чего вызываются проверки isInput[Output]Shutdown() в примере? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:18:41 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
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, кроме, разве что, многопоточного взаимодействия. Хрен там что отражено из моих вопросов выше. На конкретном протоколе у меня проблем нет. У меня проблемы на абстракции, которая должна работать на любых протоколах. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:26:53 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
schwaДругая сторона нам отправила RST в ответ на нашу операцию записи. У меня на чтение. Это и оказалось большим сюрпризом. schwaТ.е. посчитали что наше соединение не существует - оно могло быть закрыто несколько секунд назад, процесс могли просто убить или уже вообще узел за это время успел рибутнуться и он вообще ничего не знает об этом соединении. Процесс открыт. Сокет открыт. Никто не бутается - все на месте. schwaА что в этом случае делать это уже зависит от приложения - либо открывать новое соединение и как-то продолжить работу, либо игра окончена. Это уже будет привязка к протоколу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:29:14 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
schwaНе очень понятно для чего вызываются проверки isInput[Output]Shutdown() в примере? Та, просто осталось. Я там вообще все флаги блокирующего сокета перебрал. Ни один из них не меняет состояния ни до, ни после Connection Reset исключения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:30:56 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Андрей ПанфиловsendUrgentData данные не передает а шлет флаг, правда минут что поведение зависит от ОС. Спасибо. Попробую. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:31:19 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Переписал NIO на 1 поток вместо 2х, по аналогии с этим кодом 14920507 . Всё нахрен сломалось, теперь и NIO вариант без селектора не работает :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:34:21 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
DoSOfRedRiverПо поводу NIO: Селекторы достаточно эффективная и удобная вещь, почему вы их избегаете? Вообще, классический IO давно устарел, он неудобен и непрактичен, потому писать лучше сразу с использованием NIO\NIO.2Я бы не был так категоричен. Ничего не устарело, и не устареет. Это просто два разных подхода, которые в определенных местах пересекаются, а в определенных местах нет, тем самым дополняя друг друга. NIO с селекторами удобен, если нужен неблокирующий режим (как у автора), или если нужно обслуживать очень много соединений, когда подход "одно соединение - один поток" не справляется. Платой за использование NIO является бОльшая сложность его использования. Хотя в случае автора, когда нужно прост опрокидывать данные из одного сокета в другой, эта "добавленная сложность" будет не сильно выше, ибо не надо запариваться с размерами сообщений и выискивать их границы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 22:59:59 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Получилось на блокирующем 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. Дополнительные Thread.sleep() не нужны. Так как чтение блокирующее лишних циклов не возникает. Правда меня это теперь немного озадачивает. Ведь pump в одну сторону может заблокироваться и следующий уже не будет вызван. Почему вообще работает не понятно. Может один из сокетов таки сделать неблокирующим на всякий случай? В любом случае потом перепишу на selector. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 23:41:40 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
И ещё один косяк, что выход из цикла осуществляется по исключению. Этого забороть не удалось. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2013, 23:43:56 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjv, Я даже не могу придумать ни одного примера, в котором использование классического IO дало бы мне преимущество перед NIO. авторНичего не устарело, и не устареет. Точно так же можно сравнивать AWT и JavaFX. Я не хочу сказать, что эти технологии мертвы, и не нужны никому. Просто придумали уже вещи удобней и красивей. Blazkowicz, авторВышло по примеру Андрея Панфилова. Дак в примере выходит по соединению на поток, не? Тогда вообще не понимаю, какие могут быть проблемы. авторНо осталась проблема с идентификацией завершения сессии. По-моему самым эффективным способ будет посылать heartbeat, который проверяет жив ли клиент. Да и других вариантов не могу найти, потому как клиент может просто шутдаунуться. авторПотому что я хочу получить подтверждение или опровержение того на сколько блокирующие сокеты в Java "сломаны". Сломаны? Как они могут быть "сломаны"? Вроде куча народу юзает блокинг-ио, никто не жаловался особо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 00:14:41 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
DoSOfRedRiverДак в примере выходит по соединению на поток, не? Тогда вообще не понимаю, какие могут быть проблемы.Два блокирующих сокета на поток. Потому у автора и проблемы. DoSOfRedRiverПо-моему самым эффективным способ будет посылать heartbeat, который проверяет жив ли клиент. Да и других вариантов не могу найти, потому как клиент может просто шутдаунуться.Так и есть. Состояние, когда клиент подох, а сервер этого не увидел (или наоборот) - называется half-open socket. И хартбиты позволяют успешно детектировать эту ситуацию. Но автору нужно сделать прокси, вклиниться между клиентом и сервером, и просто форвардить данные из одной стороны в другую. Так что хартбиты тут не помогут. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 08:17:40 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
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 пишете, где клиент в какой-то момент просто исчезает (приложение закрыли), там можно и не логировать ничего. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 10:11:40 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
BlazkowiczschwaДругая сторона нам отправила RST в ответ на нашу операцию записи. У меня на чтение. Это и оказалось большим сюрпризом. schwaТ.е. посчитали что наше соединение не существует - оно могло быть закрыто несколько секунд назад, процесс могли просто убить или уже вообще узел за это время успел рибутнуться и он вообще ничего не знает об этом соединении. Процесс открыт. Сокет открыт. Никто не бутается - все на месте. Операция записи завершается, когда переданные данные были скопированы в буфер отправки. На следующей операции записи/чтения будет получен connection reset, если за это время произошел обрыв соединения и эта сторона соединения об этом узнала. Без закрытия соединения на другой стороне RST получить никак нельзя. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 10:14:54 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
В спойлере пример. Проверял на 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 10:42:52 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
DoSOfRedRiverЯ даже не могу придумать ни одного примера, в котором использование классического IO дало бы мне преимущество перед NIO. Google -> IO faster than NIO. DoSOfRedRiverТочно так же можно сравнивать AWT и JavaFX. Я не хочу сказать, что эти технологии мертвы, и не нужны никому. Просто придумали уже вещи удобней и красивей. Аналогия не уместна. DoSOfRedRiverДак в примере выходит по соединению на поток, не? Тогда вообще не понимаю, какие могут быть проблемы. Проблемы я объяснил в первом посте и по вашей просьбе привел текст кода, который эти проблемы вскрывает. DoSOfRedRiverПо-моему самым эффективным способ будет посылать heartbeat, который проверяет жив ли клиент. Да и других вариантов не могу найти, потому как клиент может просто шутдаунуться. Конкретику, пожалуйста. sendUrgentData() или какой ещё heartbeat? DoSOfRedRiverСломаны? Как они могут быть "сломаны"? Вроде куча народу юзает блокинг-ио, никто не жаловался особо. IO работает когда протокол заранее оговорен. У меня нет протокола. Мне нужно прокачивать любые данные любых протоколов поверх TCP. Конечно, если протокол защищен он атаки man-in-the-middle, то работать никакой вариант не будет. Но на IO у меня не получается даже обычный протокол прокачать без защиты. Почему? - описал в первом посте и привел код. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 11:05:30 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvДва блокирующих сокета на поток. Потому у автора и проблемы. У меня и по сокету на поток проблемы и два сокета на поток тоже проблемы. cdtyjvТак и есть. Состояние, когда клиент подох, а сервер этого не увидел (или наоборот) - называется half-open socket. И хартбиты позволяют успешно детектировать эту ситуацию. Но автору нужно сделать прокси, вклиниться между клиентом и сервером, и просто форвардить данные из одной стороны в другую. Так что хартбиты тут не помогут. А на sendUrgentData()? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 11:07:10 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
BlazkowiczУ меня и по сокету на поток проблемы и два сокета на поток тоже проблемы.А вы код "сокет-на-поток" выкладывали? А то я уже запутался, где что. BlazkowiczА на sendUrgentData()?В общем случае sendUrgentData() не работает. Что бы спокойно ее использовать, необходимо быть уверенным, что принимающая сторона знает, как с этой самой urgent data быть. В противном случае вы по сути будете отсылать на другую стороны какие-то левые байты, который запорят протокол, и приведут к непредсказуемым последствиям. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 11:12:03 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
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() вызвать чтобы обновить сокет? Не очевидно как-то. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 11:13:38 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
schwaОперация записи завершается, когда переданные данные были скопированы в буфер отправки. На следующей операции записи/чтения будет получен connection reset, если за это время произошел обрыв соединения и эта сторона соединения об этом узнала. Вот такой вот хитрый протокол попался. Если делать read больше нужного - отгребаешь RST. Если предотвратить RST через available(), то не происходит выхода из цикла. Ещё удивительно то что абсолютно аналогичный код на NIO API отрабатыват. Там нет available, но там и лишний read не приводит к RST. schwaБез закрытия соединения на другой стороне RST получить никак нельзя. Спасибо. Не знал. А почему бы просто не закрыть клиенту соединение тогда? Или это такой способ для одной стороны сообщить другой, что она планово закрылась? Помогите понять суть RST. Ткните носом в нужный мануал, что ли. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 11:17:51 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
maxkarВ спойлере пример. Проверял на www.apache.org порт 80. Никаких исключений. Никаких проблем с сокетами. Радостно общается с браузером потоков в 10 и при этом с HTTP keep-alive (видно по логам и сообщениям о закрытии сокетов). Соединения могут закрываться и при неактивности (т.е. конец файла определяется с обеих сторон), тоже видно по сообщениям. На HTTP у меня тоже всё работало без проблем. На другом TCP протоколе метод read из вашего примера выкинет Exception до окончания сессии обмена данными. При этом сокет ещё и закрывается, так что в него нельзя записать отклик. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 11:22:27 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvА вы код "сокет-на-поток" выкладывали? А то я уже запутался, где что. Вот мой первоначальный код. 14920906 Запускается два потока. Один работает с клиентским сокетом. Второй с серверным. (третий сидит на ServerSocket.accept(), но это не важно) cdtyjvА на sendUrgentData()?В общем случае sendUrgentData() не работает. Что бы спокойно ее использовать, необходимо быть уверенным, что принимающая сторона знает, как с этой самой urgent data быть. В противном случае вы по сути будете отсылать на другую стороны какие-то левые байты, который запорят протокол, и приведут к непредсказуемым последствиям.[/quot] Понял. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 11:25:31 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Всем большое спасибо за обсуждение. Возник ещё вопрос по NIO. Вот в этом примере 14921347 , по логике один из двух pump может заблокироваться, так как данные в эту сторону уже не идут. И второй pump не вызовется. Ведь поток заблокирован. Но на практике этого не происходит. Кто-нибудь может объяснить почему? Или мне просто повезло с протоколом? Вечером залогирую более детально. Но методы вызываются строго по очереди. Возможно в каких-то случаях они качают 0 байт, но при этом лишний вызов на TCP не происходит (смотрел снифером) Возможно я не понимаю Blocking NIO. Надо, наверное, ещё свои собственные клиент-сервер написать для теста хитрых протоколов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 11:30:15 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Blazkowicz… Вот в этом примере 14921347 , по логике один из двух pump может заблокироваться, так как данные в эту сторону уже не идут. И второй pump не вызовется. Ведь поток заблокирован. Но на практике этого не происходит. … И в catch не попадает при этом? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2013, 12:06:12 |
|
||
|
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 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547(v=vs.85).aspx Вот этой статье. авторOne technique that can be used to minimize the chance of problems occurring during connection teardown is to avoid relying on an implicit shutdown being initiated by closesocket. Instead, use one of the two explicit shutdown functions, shutdown or WSASendDisconnect. This in turn causes an FD_CLOSE indication to be received by the peer application indicating that all pending data has been received. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 11:57:16 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
schwacdtyjvТаким образом, Socket.close() является безопасным способом вырубать сокет. По крайней мере на Windows. Что и доказывает приведенный выше код. Нет. Но в конце этой статьи написано, что нужно сделать, чтобы закрыть "безопасно" нормально.Что нет? В статье написано, что надо делать shutdown/WSASendDisconnect + socketclose(). Нативный код JVM именно это и делает: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. А выставление SO_LINGER говорит о том, что мы готовы (а может быть даже намеренно хотим) закрывать сокет через RST. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 12:12:13 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
shutdown инициирует закрытие соединения. close закрывает дескриптор сокета также инициируя последовательность закрытия соединения, если оно еще не было закрыто. Без положительного значения в SO_LINGER обе функции завершаются сразу же, не дожидаясь получения подтверждений отправленных FIN сегментов. Так что после завершения последовательности вызовов Код: java 1. 2. у приложения нет никаких сведений о том, а были ли доставлены данные, которые мы отправили. В конце этой статьи же написано http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547(v=vs.85).aspx One technique that can be used to minimize the chance of problems occurring during connection teardown is to avoid relying on an implicit shutdown being initiated by closesocket. Instead, use one of the two explicit shutdown functions, shutdown or WSASendDisconnect. This in turn causes an FD_CLOSE indication to be received by the peer application indicating that all pending data has been received. To illustrate this, the following table shows the functions that would be invoked by the client and server components of an application, where the client is responsible for initiating a graceful shutdown. Client (1) Invokes shutdown(s, SD_SEND) to signal end of session and that client has no more data to send. (local timing significance only) Gets FD_READ and calls recv to get any response data sent by server Server (2) Receives FD_CLOSE, indicating graceful shutdown in progress and that all data has been received. (3) Sends any remaining response data. (local timing significance only) Invokes closesocket . Client (5) Receives FD_CLOSE indication. (6) Invokes closesocket. А теперь тоже самое, но для unix http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 12:35:01 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Пропустил (4) для сервера (4) Invokes shutdown(s, SD_SEND) to indicate server has no more data to send. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 12:40:23 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
Я так и не могу понять, к чему вы это пишете. Мы изначально говорили про то, безопасен ли Socket.close(). Так вот, я утверждаю, что безопасен. В доказательство этого я привел нативный код JVM, из которого видно, что на Windows он вызывает WSASendDisconnect + closesocket, что соответствует рекомендациям из MSDN. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.10.2013, 12:51:41 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvНа Windows работает нормально. Где именно вылез assert? Что на SocketExample.java:51 строке? Это первый же assert. Вы ключик -ea нигде не забыли при локальном тестировании? А то без него "все работает". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.10.2013, 09:20:45 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
maxkarЭто первый же assert. Вы ключик -ea нигде не забыли при локальном тестировании? А то без него "все работает".Серверный порт поменяйте, он у вас занят. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.10.2013, 09:58:07 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
cdtyjvСерверный порт поменяйте, он у вас занят. Зачем? Я никаких исключений из-за занятости не получаю. Серверный сокет нормально поднимается. Клиентский сокет тоже исключений не дает. Если assert'ы не включать, то и какое-то чтение идет (все успешно завершается в этом случае). На этом же порту потом работают другие примеры (естественно, после остановки вашего). Хотя порт я поменял. Как и ожидалось - результат ровно тот же. AssertionError на первом is.available() = 4. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.10.2013, 09:32:56 |
|
||
|
IO/NIO WTF
|
|||
|---|---|---|---|
|
#18+
maxkar , Ну продебажьте, и выясните, с чем это связано. Очевидно же, что до закрытия даже дело не доходит. В моем случае на рабочей машине не биндился серверный сокет, так как он был занят. Как бы то ни было, вопрос по Socket.close() уже закрыт, нативный код все показал. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.10.2013, 09:49:10 |
|
||
|
|

start [/forum/topic.php?all=1&fid=59&tid=2128468]: |
0ms |
get settings: |
8ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
154ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
95ms |
get tp. blocked users: |
1ms |
| others: | 230ms |
| total: | 522ms |

| 0 / 0 |
