java: один сокет при операции чтения и записи. Полный дуплекс

Я должен реализовать отправку данных с определенным исходным портом и в то же время слушать этот порт. Полный дуплекс. Кто-нибудь знает, как это реализовать на 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());
        }
}
        }

person Diyko    schedule 01.07.2014    source источник
comment
Когда вы пишете в определенный порт, это не your порт.. вы пишете в порт целевой машины, если вы не говорите, что пишете себе? Начните со слушателя...   -  person T McKeown    schedule 01.07.2014
comment
новый сокет (удаленный адрес, удаленный порт, локальный адрес, локальный порт). Мне нужно прослушивать локальный порт и одновременно отправлять сообщения с этого порта. ServerSocket не может отправлять сообщения. Обычный сокет не может слушать или, по крайней мере, я не знаю, как его реализовать   -  person Diyko    schedule 01.07.2014
comment
Вам нужен только один сокет для чтения и записи. Вы можете вызвать Socket.getInputStream для чтения и Socket.getOutputStream для записи. Однако чтение из входного потока является блокирующим вызовом, поэтому вы можете сделать это в отдельном потоке. Покажите нам часть своего кода, чтобы мы могли увидеть, что вы уже пробовали.   -  person sgbj    schedule 01.07.2014


Ответы (3)


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

Полный дуплекс довольно просто реализовать с помощью NIO:

  1. Создайте Channel для своего Socket в неблокирующем режиме.
  2. Добавьте чтение в интересующие ОП
  3. Спите по методу select() Selector
  4. Читать любые доступные для чтения байты, записывать любые доступные для записи байты
  5. Если запись завершена, удалите запись из интересующих ОП.
  6. ПЕРЕЙТИ 3.
  7. Если вам нужно записать, добавьте байты в буфер, добавьте запись в интересующие OP и активируйте селектор. (немного упрощено, но я уверен, что вы можете найти свой путь вокруг Javadoc)

Таким образом, вы будете полностью загружать исходящий буфер каждый раз, когда есть место, и одновременно читать из входящего (ну, один поток, но вам не нужно заканчивать запись, чтобы начать чтение и т. д.).

person Ordous    schedule 01.07.2014

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

https://github.com/khanhhua/full-duplex-chat

Не стесняйтесь клонировать! Это моя домашняя работа на выходные.

person Khanh Hua    schedule 12.04.2015

Основной поток:

  • Create background thread(s) that will connect to any target machines(s).
    • These threads will connect to target machines and transmit data and die
  • Create an infinite loop
    • Listen for incoming connections.
      • Thread off any connection to handle I/O

Классы:

  • Server
    • Listens for incoming connections and threads off a Client object
  • Client
    • This class is created upon the server accepting the incoming connection, the TcpClient or NetClient (i forget what java calls it) is used to send data. Upon completion it dies.
  • Target
    • Is created during the start up and connects to a specific target and send data.
    • после завершения он умирает.
person T McKeown    schedule 01.07.2014
comment
Я не отправляю ответ клиенту. Я должен иметь возможность отправлять сообщения на любой сервер и слушать prt, который я использовал для отправки своего сообщения. - person Diyko; 01.07.2014
comment
Хорошо, известен ли список серверов, к которым вы подключаетесь и отправляете данные? я предполагаю, что это должно быть - person T McKeown; 01.07.2014
comment
давайте предположим, что у нас есть сервер с именем Target с известными targetHost и targetPort. Я подключаюсь и отправляю сообщения в Target с подключением типа new Socket(remoteAddress, remotePort, myHost, myPort) и наоборот, Target отправляет на мой порт myPort, поэтому я должен все время слушать myPort. Это не обмен запрос-ответ. Цель и я отправляем друг другу сообщения в случайном порядке - person Diyko; 01.07.2014
comment
звучит прямо вперед... основной поток - слушатель... затем создайте поток для подключения к этой цели... - person T McKeown; 01.07.2014
comment
Вы имеете в виду новый ServerSocket (myport) и создаете прослушиватель? Тогда как отправить сообщение на определенный порт без предварительного запроса? Я не могу создать другой сокет на том же локальном порту - person Diyko; 01.07.2014
comment
да... затем при соединении вы отключаете его для обработки ввода-вывода, основной поток должен находиться в цикле, который просто принимает соединения. - person T McKeown; 01.07.2014
comment
вы отправляете сообщения этим целям, используя их собственную ветку... Я закодирую ее в своем ответе.. дайте мне несколько. - person T McKeown; 01.07.2014
comment
В таком случае проблема с отправкой сообщений. Я не могу создать другой сокет с тем же локальным портом и не знаю, как отправить сообщение с существующим сокетом сервера на мою цель без предварительного запроса от цели - person Diyko; 01.07.2014
comment
чтобы цель подключилась к вам и идентифицировала себя? все еще не проблема, используйте эту информацию и подключитесь обратно - person T McKeown; 01.07.2014
comment
я никогда не предлагал вам создавать более 1 сокета для прослушивания, у вас может быть только один прослушиватель для порта... Я не думаю, что вы понимаете, что я вам говорю.. - person T McKeown; 01.07.2014
comment
Target не подключается ко мне. Я подключился к Target и использую правильный локальный порт, иначе Target отклонит меня. Это вовсе не связь запрос-ответ. - person Diyko; 01.07.2014
comment
Я не могу создать сервер и клиент, это должен быть только один сокет - person Diyko; 01.07.2014
comment
хорошо, но вы бы знали порт.. порт находится на цели, а не вы.. в чем проблема? - person T McKeown; 01.07.2014
comment
Я не могу создать сервер и клиент, это должен быть только один сокет — - person Diyko; 01.07.2014
comment
да, сервер прослушивает соединения... не будет ли входящих запросов на соединение? - person T McKeown; 01.07.2014
comment
если я создаю сервер, я не могу отправлять свои сообщения без запроса от Targer, но я должен - person Diyko; 01.07.2014
comment
вы совсем плохо объяснили... я зря трачу время... вы должны быть в состоянии объяснить более ясно... - person T McKeown; 01.07.2014
comment
Да, вы можете... вы можете создать сервер и подключиться... почему вы думаете, что не можете? - person T McKeown; 01.07.2014