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
нов Socket(remoteAddress, remotePort, localAddress, localPort). Трябва да слушам на локален порт и в същото време да изпращам съобщения от този порт. ServerSocket не може да изпраща съобщения. Plain Socket не може да слуша или поне не знам как да го внедря   -  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. Спете с метода на Selector select()
  4. Прочетете всички четими байтове, запишете всички записваеми байтове
  5. Ако записът е завършен, премахнете записа от интересните OP
  6. МИНЕТЕ НА 3.
  7. Ако трябва да пишете, добавете байтове към буфер, добавете запис към интересуващи OPs и селектор за събуждане. (леко опростен, но съм сигурен, че можете да се ориентирате в Javadoc)

По този начин вие ще зареждате напълно изходящия буфер всеки път, когато има място и четете от входящия едновременно (е, една нишка, но не е нужно да завършите писането, за да започнете да четете и т.н.).

person Ordous    schedule 01.07.2014

Бях се сблъскал със същия въпрос и реших сам да си отговоря. Бих искал да споделя с вас репо кода. Наистина е просто, можете да получите идеята да накарате нещата си да работят. Това е сложен пример. Стъпките случайно изглеждат като решението на Ordous.

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 с връзка като нов Socket(remoteAddress, remotePort, myHost, myPort) и обратното Target изпраща до моя порт myPort, така че трябва да слушам myPort през цялото време. Това не е комуникация заявка-отговор. Target и аз изпращаме съобщения един на друг в произволен ред - person Diyko; 01.07.2014
comment
звучи право напред... главна нишка слушател... след това генерира нишка, за да се свърже с тази цел... - person T McKeown; 01.07.2014
comment
имаш предвид new ServerSocket(myport) и създаване на слушател? Тогава как да изпратите съобщение до определен порт без предварителна заявка? Не мога да създам друг Socket на същия локален порт - person Diyko; 01.07.2014
comment
да... след това при връзка, която изключвате, за да се справите с i/o, основната нишка трябва да бъде в цикъл, който приема само връзки. - person T McKeown; 01.07.2014
comment
вие изпращате съобщения до тези цели, използвайки тяхната собствена нишка... Ще го кодирам в отговора си.. дайте ми няколко. - person T McKeown; 01.07.2014
comment
В такъв случай възниква проблем с изпращането на съобщения. Не мога да създам друг сокет със същия локален порт и не знам как да изпратя съобщение със съществуващ сървърен сокет към моя Target без предварителна заявка от Target - person Diyko; 01.07.2014
comment
така че целта ще се свърже с вас и ще се идентифицира? все още не е проблем, използвайте тази информация и се свържете обратно - person T McKeown; 01.07.2014
comment
Никога не съм предлагал да създадете повече от 1 сокет за слушане, можете да имате само един слушател за порт... Не мисля, че разбирате какво ви казвам.. - person T McKeown; 01.07.2014
comment
Target не се свързва с мен Трябва да се свържа с Target и да използвам правилния localPort, в противен случай 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