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

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

19.12.2011, 22:03. Показов 10527. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru