2014-02-11 6 views
3

Я пытаюсь написать простую консольную программу, которая позволяет отправлять и получать сообщения String. Проблема, с которой я сталкиваюсь, заключается в том, что я не знаю, как одновременно запускать код приема и код отправки.Как запустить эти две петли одновременно? (Java)

Индивидуально, классы работают. Я могу получать пакеты и отправлять пакеты, но заставить их работать сразу кажется мне невозможным.

Я искал многопоточность, но поскольку мои знания все еще очень просты, я не могу понять, как это работает.

Это код, который я использую в настоящее время. Я сам написал класс Dialog и нашел два других класса в Интернете.

Dialog класс:

import java.util.Scanner; 


public class Dialog { 

Scanner scanner = new Scanner(System.in); 
User user = new User(); 
Network net = new Network(); 

ThreadReceive tr = new ThreadReceive(); 
ThreadSend ts = new ThreadSend(); 


public void run() { 

    System.out.println("WELCOME"); 

    System.out.print("Port: "); 
    while(!user.setPort(giveInput())) { 
     System.out.println("Enter a valid port."); 
    } 

    System.out.print("IP: "); 
    user.setIP(giveInput()); 

    System.out.println(); 
    System.out.println("--- CONVERSATION STARTED ---"); 

    tr.receive(user.getIP(), user.getPort()); // Starts receiving loop (within ThreadReceive class). 

    while (true) { // Starts sending loop. 
     ts.sendMessage(giveInput(), user.getIP(), user.getPort()); // Sends packet when input is given. 
    } 

} 


private String giveInput() { 

    String input = scanner.nextLine(); 
    return input; 

} 

} 

Принимающий класс:

import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 

public class ThreadReceive extends Thread { 

public void receive(String ip, int port) { 

    try { 

     // Create a socket to listen on the port. 
     DatagramSocket dsocket = new DatagramSocket(port); 

     // Create a buffer to read datagrams into. If a 
     // packet is larger than this buffer, the 
     // excess will simply be discarded! 
     byte[] buffer = new byte[2048]; 

     // Create a packet to receive data into the buffer 
     DatagramPacket packet = new DatagramPacket(buffer, buffer.length); 

     // Now loop forever, waiting to receive packets and printing them. 
     while (true) { 
      // Wait to receive a datagram 
      dsocket.receive(packet); 

      // Convert the contents to a string, and display them 
      String msg = new String(buffer, 0, packet.getLength()); 
      System.out.println(packet.getAddress().getHostName() + ": " + msg); 

      // Reset the length of the packet before reusing it. 
      packet.setLength(buffer.length); 
     } 

    } 

    catch (Exception e) { 
     System.err.println(e); 
    } 

} 

} 

Отправив класс:

import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 


public class ThreadSend extends Thread { 

public void sendMessage(String message, String ip, int port) { 

     try { 
      byte[] data = message.getBytes(); 

      InetAddress address = InetAddress.getByName(ip); 

      DatagramPacket packet = new DatagramPacket(data, data.length, address, port); 

      DatagramSocket datagramSocket = new DatagramSocket(); 
      datagramSocket.send(packet); 
     } 

     catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

Кроме того, есть ли способ, чтобы проверить, могу ли я принимать пакеты? Я тестировал его с другом, но было бы гораздо удобнее сделать это сам.

Спасибо!

+4

Не могли бы вы просто сделать две программы, чтобы разговаривать друг с другом, а не пытаться сделать это в одном? – doctorlove

+0

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

+1

Замечание, не связанное с вопросом: рассмотрите использование Executors/ThreadFactory вместо создания подклассов Thread: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html – Puce

ответ

0

Вы не используете Threads правильно.

Логика должна быть в методе run.

Я предлагаю вам использовать queue, например ArrayBlockingQueue, для передачи параметров вашим потокам.Например, вы могли бы иметь метод, чтобы добавить элементы в этой очереди

public void addMessage(String message) { 
    synchronized(inputQueue) { 
      inputQueue.offer(r); 
      inputQueue.notify(); 
    } 
} 

и метод выполнения будет использовать эти элементы, как так:

public void run() { 
     try { 
      while(!running) 
        synchronized (inputQueue) { 
         inputQueue.wait(); // you can have a timeout also... 
          String message = this.inputQueue.poll(); 
           // use the message item.... 
           // in your case send it to the other user. 
         } 
        }  
       } 
     } catch (Exception e) { 
      /////// your exception handler 
     } 
} 

Рекомендуем также Запомнить начать свои темы:

Thread t = new MyThread(); 
t.start(); /// Start the thread !!! 

PS: Сообщения могут быть любыми объектами, здесь используются строки, поскольку я основывался на этом на каком-либо из моего кода, где я использую

Queue<String> 
+0

Хорошо, поэтому я сначала инициализирую две темы. Однако я не понимаю, как передать параметры методам run(). – Daan

+0

Извините, я забыл queue.wait(). Отредактировано –

+0

Как только потоки начинаются, он ожидает, что inputQueue будет уведомлен. После вызова addMessage он уведомляет потоки, ожидающие ввода input, и поэтому поток возобновляет и начинает обработку очереди. Как только он закончится, так как он находится в цикле while, он снова ждет уведомления о вызове inputQueue. –

0

Ознакомьтесь с руководством Beej по сетевому программированию: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html - Это даст вам еще несколько примеров, чтобы взглянуть на них. Что касается тестирования, вы можете настроить виртуальную машину или использовать другой компьютер, который у вас есть. Назад, когда мне пришлось учиться в школе в школе, мы бы ssh в два отдельных ящика Linux, чтобы проверить наш код.

РЕДАКТИРОВАТЬ: Также, чтобы убедиться, что вы правильно получаете сообщение, вы можете заставить отправителя и получателя распечатать полученные пакетные данные. Или вы можете просто напечатать простую строку, чтобы сказать, что пакет был получен.

Вы также можете проверить TCP, а не UDP, если вы хотите непрерывный поток. UDP просто создает пакет датаграммы и отправляет его в сети, тогда как TCP создает постоянное соединение между двумя узлами.

+0

Хорошо для UDP vs TCP вы можете прочитать: http://www.diffen.com/difference/TCP_vs_UDP Речь идет о скорости и надежности в основном. –

+0

@LaurentB хорошо дополнение. Определенно, что-то рассмотреть, если вы решите посмотреть на TCP. –

Смежные вопросы