Сокеты Java: можете ли вы отправлять сообщения из одного потока и получать из другого? - PullRequest
5 голосов
/ 09 декабря 2011

Возможно, это очень простой вопрос, но мне трудно найти ответ.

Можно ли записывать один поток в выходной поток Socket, а другой поток - из входного потока Socket?

Редактировать: это клиентское приложение, которое обращается к внешнему серверу. Я не пытаюсь заставить эти два потока говорить друг с другом. Извините за двусмысленность.

Ответы [ 7 ]

5 голосов
/ 09 декабря 2011

Предполагая, что вы имеете в виду, что потоки используют один и тот же сокет для связи с внешним субъектом, а не друг с другом, это довольно часто, так как вы часто не хотите блокировать, ожидая чтения из сокета.

Резьба1:

block on read
on recieve message - do something

Резьба2:

do things
on something happening - write to socket

Если вместо этого вы имели в виду просто внутреннее взаимодействие двух потоков, вы должны рассмотреть альтернативы без сокетов.

Редактировать: Также остерегайтесь потенциальных проблем параллелизма, поэтому проверьте, являются ли используемые вами потоки безопасными для потоков.

2 голосов
/ 09 декабря 2011

Люди смущены вашим вопросом, и поэтому половина говорит: «Да, но это не так, как два потока должны общаться друг с другом», а другой интерпретирует ваш вопрос как «Я хочу, чтобы один поток всегда записывал в сокет»и другой поток всегда читает данные из сокета, поэтому моя программа может отправлять и получать одновременно. "Более поздняя интерпретация означает, что эти два потока НЕ ​​используют сокет для обмена информацией друг с другом, но другой механизм, который делает это менее неприглядным.Ответ ДА.Сокеты являются двунаправленными, поэтому вы можете отправлять и получать данные одновременно.Это не значит, что для этого нужно использовать два потока.

Теперь это очень необычно.За все время, что я работал над протоколами сокетов (POP, IMAP, HTTP и т. Д.), Я никогда не сталкивался с ситуацией, когда это было так, или, говоря иначе, я никогда не видел протокол, который требует этого,В какой-то момент протокол является синхронным, и один из этих концов должен ждать, прежде чем он отправит дополнительную информацию или прочитает дополнительную информацию.Единственный случай, о котором я мог подумать, это что-то вроде RTMP, аудио или потокового видео.Тем не менее, я думаю, что большинство из них используют некую форму неблокирующего ввода / вывода, поэтому имитируют одновременную связь.

И это следующее, что вы можете рассмотреть.Когда вы обрабатываете сообщения из сокета, вы можете проверить сокет на наличие данных, прежде чем блокировать его.Если он там есть, прочитайте его, если у вас есть данные для записи, проверьте и можете ли вы писать без блокировки, а затем запишите это.Или используйте неблокирующие сокеты IO.Таким образом, у вас есть только один поток для чтения / записи в сокет, и синхронизация между операциями чтения / записи не составляет труда.С потоками вам придется использовать блокировку или семафоры или что-то другое для координации между ними, что может привести к мертвым блокировкам.

1 голос
/ 09 декабря 2011

Вы можете читать один поток, в то время как другой пишет. AFAIK Это, пожалуй, самый распространенный вариант использования для блокировки сокетов.

Можно иметь несколько потоков, выполняющих оба, но это не просто, и вам редко требуется более одного каждого.


Вы можете иметь два потока, взаимодействующих в одном процессе. Это то, что я часто использую в модульных тестах, где компоненты клиента и сервера находятся в одном процессе.

Вы даже можете использовать один поток для чтения и записи с обоих концов. http://vanillajava.blogspot.com/2011/11/java-puzzle-single-threaded-client.html

Альтернативы могут заключаться в использовании потокового потока (потоков), который немного быстрее, или BlockingQueue (s) или Exchanger с ByteBuffers, или нескольких других опций. ;)

1 голос
/ 09 декабря 2011

Другими словами, вы хотите использовать сокет для отправки информации из одного потока в другой поток? Да, это возможно. Я бы настоятельно рассмотрел другой маршрут (они могут просто передать друг другу ссылку, так что я бы подумал, что это будет лучше), но он должен работать.

При изучении работы сокетов и связанных с этим проблем хранение их в одном приложении часто значительно упрощает ситуацию, и я это настоятельно рекомендую.

Но для производственного кода я бы рекомендовал использовать ссылки или потокобезопасную очередь или что-то подобное.

Редактировать: в ответ на ваш комментарий и правки:

Да.

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

1 голос
/ 09 декабря 2011

Нет ничего плохого в том, чтобы выполнять эту операцию, если у вас есть веская причина общаться таким образом, а не с помощью других потоковых методов коммуникации.прослушивание / запись в одно и то же гнездо различных приложений.

0 голосов
/ 09 декабря 2011

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

0 голосов
/ 09 декабря 2011

Да, но какой поток вы хотите использовать для создания "буфера"?Это должно быть что-то вроде BlockingQueue

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...