#java #blocking #serversocket
#java #блокировка #serversocket
Вопрос:
Я пишу код для сервера, который помог бы двум разным приложениям на разных платформах взаимодействовать друг с другом. Чтобы немного визуализировать это, это было бы что-то вроде этого :
Приложение 1<——> Сервер<——> Приложение 2
Сервер извлекает var1 из app2, записывает его в app1, затем считывает var2 из app1 и записывает его в app2. Вот так :
while(true){
var1 = app2stream.readInt();
app1stream.writeInt(var1);
var2 = app1stream.readDouble();
app2stream.writeDouble(var2);
}
Моя проблема в том, что в какой-то момент у меня есть этот код на моем сервере :
app1.accept();
app2.accept();
Это означает, что независимо ни от чего, и учитывая тот факт, что сервер всегда запущен, app1 — это тот, который должен подключиться первым, поскольку app1.accept() — это метод блокировки.
Есть ли какой-либо способ обойти это? Было бы здорово разрешить двум приложениям подключаться к серверу независимо от того, кто «пришел» первым, а затем дождаться, пока сервер выполнит приведенный выше код. Могу ли я использовать потоки только для части accept(), а затем передавать потоки в другой поток? Я немного читал о каналах, но немного запутался, любые примеры были бы великолепны.
Комментарии:
1. Рассматривали ли вы реализацию JMS? Похоже, это именно то, для чего он предназначен.
Ответ №1:
Используйте NIO
Это позволяет вам создавать неблокирующие сокеты (включая accept), используя Selector
класс.
По сути, это дает вам гораздо более простой доступ к системным библиотекам и возможность обрабатывать ваши задачи без необходимости многопоточности.
Комментарии:
1. Я читаю статью, на которую вы ссылались, спасибо, я вернусь, если у меня возникнут какие-либо вопросы!
2. мне было интересно, возможно ли использовать каналы NIO и класс selector для сервера, но при этом использовать простой DataOutput / InputStream в двух других приложениях (которые являются клиентами), чтобы мне не пришлось менять слишком много кода?
3. Ну, конечно. Если уж на то пошло, они могли бы быть написаны на perl 🙂 Вы просто используете сокеты TCP.
Ответ №2:
Есть только один вызов accept и один серверный сокет. Вы можете определить, какое приложение подключилось, как только они подключатся. Если вы не можете получить это из сведений о подключении, попросите их отправить authcode (в любом случае, вероятно, это хорошая идея), который вы можете сопоставить с вашим приложением.
Ответ №3:
Вероятно, вам следует относиться к ним обоим одинаково, если они не говорят иначе.
Например, когда каждый сокет подключается, отправьте запрос «какой клиент?» Сообщение.
Затем проверьте, отвечает ли клиент на 1 или 2.
Если оба отвечают 1 или чем-то еще, просто отключите оба.
Ответ №4:
Я думаю, что «стандартный» способ сделать это — заставить сервер прослушивать порт, и когда приходит сообщение, немедленно запустить новый поток для его обработки, затем вернуться к прослушиванию другого сообщения. Затем, как говорит Glowcoder, сделайте все соединения в одном цикле и заставьте его определить, что есть что, после подключения.
Я полагаю, альтернативой является наличие нескольких потоков, каждый из которых прослушивает разные порты. Я никогда не пытался этого сделать, я не уверен, что оно будет блокироваться до тех пор, пока не будет установлено соединение, и поэтому вы никогда не перейдете к другому потоку.