#java #sockets #duplex #socketchannel
#java #сокеты #дуплекс #socketchannel
Вопрос:
Я должен реализовать отправку данных с определенного исходного порта и в то же время прослушивать этот порт. Полный дуплекс. Кто-нибудь знает, как это реализовать на Java. Я попытался создать отдельный поток для прослушивания входного потока сокета, но это не работает. Я не могу привязать ServerSocket и клиентский сокет к одному и тому же исходному порту и то же самое с netty. Есть ли какое-либо решение для скучного дуплекса?
init(){
socket = new Socket(InetAddress.getByName(Target.getHost()), Target.getPort(), InetAddress.getByName("localhost"), 250);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
}
private static void writeAndFlush(OutputStream out, byte[] b) throws IOException {
out.write(b);
out.flush();
}
public class MessageReader implements Runnable {
@Override
public void run() {
//this method throw exception EOF
read(in);
}
private void read(DataInputStream in){
while (isConnectionAlive()) {
StringBuffer strBuf = new StringBuffer();
byte[] b = new byte[1000];
while ((b[0] = bufferedInputStream.read(b)) != 3) {
strBuf.append(new String(b));
}
log.debug(strBuf.toString());
}
}
}
Комментарии:
1. Когда вы записываете на определенный порт, это не
your
порт.. вы записываете на порт целевой машины, если только вы не говорите, что пишете для себя? Начните с прослушивателя…2. новый сокет (remoteAddress, RemotePort, localAddress, LocalPort). Мне нужно прослушивать локальный порт и одновременно отправлять сообщения с этого порта. ServerSocket не может отправлять сообщения. Обычный сокет не может прослушиваться или, по крайней мере, я не знаю, как это реализовать
3. Вам нужен только один сокет для чтения и записи. Вы можете вызвать Socket.getInputStream для чтения и Socket.getOutputStream для записи. Однако чтение из входного потока является блокирующим вызовом, поэтому вы можете захотеть выполнить это в отдельном потоке. Покажите нам часть вашего кода, чтобы мы могли увидеть, что вы уже пробовали.
Ответ №1:
То, что вы пытаетесь сделать, довольно странно: ServerSocket
это полностью реализованный сокет, который принимает соединения, обрабатывает свои собственные сообщения, и вы определенно не можете подключить к нему другой сокет поверх него.
Полный дуплекс довольно просто выполнить с помощью NIO:
- Создайте
Channel
для своегоSocket
в неблокирующем режиме - Добавьте чтение в интересующие операции
- Переход в спящий режим с помощью метода
Selector
‘sselect()
- Считывать любые читаемые байты, записывать любые доступные для записи байты
- Если запись завершена, удалите запись из интересующих операций
- ПЕРЕХОД 3.
- Если вам нужно записать, добавьте байты в буфер, добавьте запись в интересующие операции и активируйте селектор. (немного упрощенный, но я уверен, что вы сможете найти свой путь вокруг Javadoc)
Таким образом, вы будете полностью загружать исходящий буфер каждый раз, когда есть свободное место, и одновременно читать из входящего (ну, в одном потоке, но вам не нужно заканчивать запись, чтобы начать чтение и т.д.).
Ответ №2:
Я столкнулся с тем же вопросом и решил ответить на него сам. Я хотел бы поделиться с вами, ребята, репозиторием кода. Это действительно просто, вы можете понять, как заставить ваши вещи работать. Это сложный пример. Шаги случайно выглядят как решение Ордуса.
https://github.com/khanhhua/full-duplex-chat
Не стесняйтесь клонировать! Это моя домашняя работа на выходные.
Ответ №3:
Основной поток:
- Создайте фоновый поток (потоки), который будет подключаться к любым целевым машинам.
- Эти потоки будут подключаться к целевым машинам, передавать данные и умирать
- Создайте бесконечный цикл
- Прослушивание входящих подключений.
- Отключите любое соединение для обработки ввода-вывода
- Прослушивание входящих подключений.
Классы:
- Сервер
- Прослушивает входящие соединения и потоки от объекта клиента
- Клиент
- Этот класс создается на сервере, принимающем входящее соединение, TcpClient или NetClient (я забыл, как это называется Java) используется для отправки данных. По завершении он умирает.
- Цель
- Создается во время запуска и подключается к определенной цели и отправляет данные.
- после завершения он умирает.
Комментарии:
1. Я не отправляю ответ клиенту. Я должен иметь возможность отправлять сообщения на любой сервер и прослушивать prt, который я использовал для отправки своего сообщения
2. хорошо, известен ли список серверов, к которым вы подключаетесь и отправляете данные? я предполагаю, что это должно было бы быть
3. давайте предположим, что у нас есть некоторый сервер с именем Target с известными targetHost и targetPort. Я подключаюсь и отправляю сообщения к цели с подключением типа new Socket (remoteAddress, RemotePort, myHost, myPort), и наоборот, цель отправляет на мой порт myPort, поэтому я должен постоянно прослушивать myPort. Это не обмен запросами-ответами. Цель и я отправляем сообщения друг другу в случайном порядке
4. звучит прямолинейно … основной поток — слушатель… затем создайте поток для подключения к этой «цели»…
5. вы имеете в виду новый ServerSocket (myport) и create listener? Тогда как отправить сообщение на определенный порт без предварительного запроса? Я не могу создать другой сокет на том же локальном порту