Форум программистов, компьютерный форум, киберфорум
Java: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/56: Рейтинг темы: голосов - 56, средняя оценка - 4.82
0 / 0 / 0
Регистрация: 08.06.2011
Сообщений: 63

Передача данных с использованием SocketChannel

19.12.2011, 22:03. Показов 10568. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
При регистрации селектором нового соединения создаем SocketChannel, устанавливаем его в неблокирующий режим, регистрируем его в том же селекторе.
Затем через цепочку SocketChannel->Socket->OutputStream->PrintWriter отправляем клиенту данные (строка текста).
Проблема в том, что клиент, пытаясь получить эти данные, виснет (т.е. НЕСКОНЧАЕМО долго их ждет).

Код клиента:
Java
1
2
3
4
5
6
socket = new Socket(serverIP, port);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine;
if((inputLine = in.readLine()) != null) {
   System.out.println(inputLine);
}
Код сервера:
Java
1
2
3
4
5
6
7
8
9
10
11
12
if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
     Socket socket = serverSocket.accept();
     SocketChannel socketChannel = socket.getChannel();
     socketChannel.configureBlocking(false);
     socketChannel.register(selector, SelectionKey.OP_READ);
     try {
        PrintWriter out = new PrintWriter(socket.getOutputStream());
        out.println(data);
     } catch (IOException e) {
        e.printStackTrace();
     }
// ...
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.12.2011, 22:03
Ответы с готовыми решениями:

Передача файла через SocketChannel
Всем привет. Наверняка кто-нибудь сталкивался с такой задачей: нужно передать файл через сокетное соединение (nio). Перерыл кучу...

Передача данных по Анонимным (Неименованым) каналам с последующим использованием этих данных
Всем доброго времени суток. Нужна помощь: Имеется Сервер и Клиент связанные анонимным каналом. Через анонимный канал нужно передать 4...

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

11
0 / 0 / 2
Регистрация: 30.06.2011
Сообщений: 173
20.12.2011, 10:19
Попробуй в клиенте инициализацию сокета сделать так:
socket = new Socket();
socket.connect(new InetSocketAddress(host, port),5000);
По идее если не произойдет соединения, то клиент отвалится через пять секунд с исключением.

Мне почему-то кажется, что все-таки данные не доходят до клиента.
0
0 / 0 / 0
Регистрация: 08.06.2011
Сообщений: 63
20.12.2011, 11:29  [ТС]
Как я уже говорил, проблема вовсе не в соединении. Этот этап проходит без сучков и задоринок. Таймаут здесь не поможет и ничего не подскажет. Клиент погружается в дупл здесь:
Java
1
if((inputLine = in.readLine()) != null) {
0
0 / 0 / 2
Регистрация: 30.06.2011
Сообщений: 173
20.12.2011, 18:26
Если, соединение проходит нормально, зависание на строчке
if((inputLine = in.readLine()) != null) {

это не зависание, это просто твой клиент ждет когда в потоке in появятся данные и он их прочитает.
У меня прога тоже работает с сервером по этому принципу, - это так называемый блокирующий ввод-вывод.
Мое мнение, - твоя прога не висит, просто в потоке in нет данных!!!
0
0 / 0 / 0
Регистрация: 08.06.2011
Сообщений: 63
20.12.2011, 19:36  [ТС]
Самое печальное - что я это и сам понимаю!
Но данные с сервера отправляются с ходу после соединения.
Так почему же их нет в ИНе у клиента, а?
0
0 / 0 / 0
Регистрация: 22.07.2009
Сообщений: 457
20.12.2011, 20:49
вы channel то и не используете вовсе на серверной стороне, у вас обычное сокетное соединение , т.е. не nio. Добавьте out.flash(); после out.println(data);
0
0 / 0 / 0
Регистрация: 08.06.2011
Сообщений: 63
20.12.2011, 21:02  [ТС]
Конструктивное замечание!
Но все же SocketChannel я упомянул не зря. В реализации моего сервера на нитях у меня подобной проблемы не возникает. Сервер передает, клиент принимает и все счастливы!
А в данном случае даже out.flash(); не помогает.
Данные от сервера уходят... и никуда не приходят.
0
0 / 0 / 0
Регистрация: 22.07.2009
Сообщений: 457
20.12.2011, 21:52
Данные от сервера [bold]уходят[/bold] ... и никуда [bold]не приходят[/bold] .
Так не бывает в TCP/IP сокетах, значит утверждение неверно . Если выкинуть все связанное с чанелами из приведенного кода сервера, то получится типичный пример из учебника, который всегда работает.
0
0 / 0 / 0
Регистрация: 08.06.2011
Сообщений: 63
20.12.2011, 22:14  [ТС]
Но тем не менее. Код приведен. У меня не работает.
(я, в принципе, не удивлюсь, если случится такая же история, как с регулярными выражениями)
0
0 / 0 / 0
Регистрация: 08.06.2011
Сообщений: 63
21.12.2011, 03:02  [ТС]
Я все таки до кое-чего доковырялся.
Сервер действительно должен был сказать "out.flush();". Но вот в чем затрах:
Если в приведенный код вставить вызов сего чудного метода, на нем произойдет исключение IllegalBlockingModeException, что означает, что в неблокирующем режиме так поступать нельзя.
Java
1
2
3
4
5
6
7
try {
   PrintWriter out = new PrintWriter(socket.getOutputStream());
   out.println(data);
   out.flush();
} catch (IOException e) {
   e.printStackTrace();
}
Надо поместить перед установкой неблокирующего режима канала. Тогда все работает.

Но теперь появляется еще одна проблема. Когда селектор сигнализирует о поступлении данных от клиента, мы их считываем, обрабатываем, и пытаемся отправить ответ:
Java
1
2
3
4
5
6
7
try {
   PrintWriter out = new PrintWriter(socketChannel.socket().getOutputStream());
   out.println(data);
   out.flush();
} catch (IOException e) {
   e.printStackTrace();
}
И опять же: flush() использовать нельзя, поскольку канал в неблокирующем режиме (мы это определили, когда регистрировали в селекторе новое соединение).
Если же попытаться перед этой операцией перевести канал в блокирующий режим, выпадет все то же знакомое IllegalBlockingModeException.
Я глядел в классе AbstractSelectableChannel.configureBlock ing(boolean) - там действительно вызывается это исключение в случае, если кто-то хочет установить блокирующий режим и при этом внутренний массив типа SelectionKey[] не пуст.
Интересно только, как его опустошить, и еще более интересно надо ли это вообще.
Может, это дело по-другому реализуется?
0
0 / 0 / 0
Регистрация: 22.07.2009
Сообщений: 457
21.12.2011, 17:34
И опять же: flush() использовать нельзя, поскольку канал в неблокирующем режиме
Как то странно, потому что понятие блокировки относится к чтению из сокета, а не к записи.

Если уж вы используете нио, то проще было бы и чтение и запись осуществлять через каналы, как это описано в литературе. А у вас получился гибрид (нио + ио). Возможно, в этом случае есть нюансы, с которыми вы и столкнулись.
0
0 / 0 / 1
Регистрация: 08.11.2011
Сообщений: 9
21.12.2011, 17:47
Может функция available() класса InputStream поможет?

Returns the number of bytes that can be read (or skipped over) from this input stream without blocking by the next caller of a method for this input stream.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.12.2011, 17:47
Помогаю со студенческими работами здесь

Передача данных с использованием Intent
Добрый день! Не получается перенести текст введённый с одного активити в другой. Код первого активити: Intent intent = new...

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

Передача данных с использованием Html.BeginForm
Привет друзья. У нас есть страничка Page. @{ int a = 7; } @using (Html.BeginForm("funk", "PageTest", FormMethod.Post, new { enctype...

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

Передача данных между консолью с использованием Pipe
Добрый день! Не получается организовать передачу данных между двумя консольными приложениями при использовании буфера с типом wchar_t....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек SDL3 и Box2D из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия SDL 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual. . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru