#java #multithreading #sockets #p2p
#java #многопоточность #сокеты #p2p
Вопрос:
Возможно ли написать программу, которая служит одновременно сервером и клиентом? Предположим, у меня есть три экземпляра программы P: P1, P2 и P3.
- В одном случае использования P2 запрашивает файл у P1.
- В то время как P1 передает файл на P2, P1 запрашивает файл из формы P3.
- P3 передает файл на P1. (На этом этапе P3 может загружать с P1 или P2.)
Концептуально, я должен быть в состоянии сделать это, запуская серверную часть в потоке каждый раз, когда поступает запрос. Есть ли другой подход к этому?
Редактировать:
У меня есть некоторый начальный код, который позволяет мне, как клиенту, запрашивать файл с сервера (при условии, что указан номер порта сервера и имя файла). Тот же код также запускает серверный поток, который параллельно прослушивает входящие запросы. Таким образом, по сути, эта кодовая база служит одноранговой (как клиентской, так и серверной).
Но сейчас моя проблема заключается в том, что после выполнения первого запроса к файлу код бесконечно повторяется в серверной части, фактически не позволяя мне делать какие-либо дополнительные запросы в качестве клиента. Тогда мой вопрос таков: могу ли я оставить сокет открытым, пока сервер прослушивает порт, без необходимости бесконечного цикла сервера? Таким образом, я могу запускать сервер в «фоновом режиме» и иметь возможность отправлять команды клиенту по мере необходимости.
Ответ №1:
Да, это вполне возможно, и на самом деле очень распространено. Большинство корпоративных приложений используют это.
Например, пользователь запрашивает веб-страницу для отображения в браузере с веб-сервера. Точнее, запрос пользователя показать статью 23.
Затем веб-сервер запрашивает информацию базы данных, касающуюся статьи 23. С ответом от сервера базы данных веб-сервер создает хорошо отформатированную HTML-страницу для отображения пользователю.
Концептуально, использование сети — это просто способ общения, то есть отправки или получения информации. Это не сильно отличается от записи / чтения из файла. И в Linux это то же самое.
Итак, да, каждый сервер может прослушивать порт и в то же время быть клиентом другого сервера. Классическая реализация для сервера в JAVA word заключается в использовании одного потока на клиента на стороне сервера.
Это означает, что когда P2 подключается к P1, между P1 и P2 устанавливается новое соединение, и что P2 использует поток для записи ответа на P1… В большинстве простых случаев тот же поток фактически запрашивает недостающую информацию с другого сервера, поэтому отправляет запрос и ожидает ответа.
Отвечая на вашу правку :
Классическая многопоточная реализация сервера заключается в прослушивании порта с некоторым бесконечным циклом. Каждый раз, когда вы обнаруживаете запрос на подключение от клиента, вы устанавливаете соединение, согласовываете порт, который будет использоваться на клиенте и сервере для этого обмена данными, и делегируете это соединение другому потоку (обычно используя пул потоков, чтобы не использовать поток повторно для следующего клиента по завершении обмена данными).
Таким образом, у вас всегда есть доступ к вашему потоку для ответа на запрос подключения от клиентов.
Комментарии:
1. Спасибо за ваш ответ. Я вскоре опубликую свой код. Возможно, я смешиваю два разных вопроса в один. Но пока я понимаю, о чем вы говорите, и, вероятно, моя реализация соответствует вашему комментарию за вычетом пула потоков. Я создаю совершенно новый поток каждый раз, когда поступает запрос. Кроме того, я думаю, что использую один и тот же порт как для клиента, так и для сервера (поскольку они находятся на одном компьютере).