Frage

I'm trying to write a simple console program that allows me to send and receive String messages. The problem I am encountering though, is that I don't know how to run the receiving code and the sending code simultaneously.

Individually, the classes are working. I can receive packets and send packets, but making them run at once seems impossible to me.

I've looked into multi-threading but since my knowledge is still very basic, I can't seem to understand how it really works.

This is the code I'm currently using. I wrote the Dialog class myself and found the other two classes on the internet.

Dialog class:

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;

}

}

Receiving class:

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);
    }

}

}

Sending class:

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();
        }
    }

}

Also, is there any way to test if I can receive packets? I've been testing it with a friend but it would be much more convenient to do it myself.

Thanks!

War es hilfreich?

Lösung

You are not using Threads correctly.

The logic should be in the run method.

I suggest you use a queue such as an ArrayBlockingQueue to pass parameters to your threads. For instance, you could have a method to add elements to this queue

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

And the run method will use these elements as so :

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
        }
}

Also Remember to start your threads :

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

PS : The messages can be any object here is used strings as i based this on some of my code where i'm using a

Queue<String>

Andere Tipps

Check out Beej's Guide to Network Programming: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html -- This will give you some more examples to take a look at. As far as testing goes, you could set up a virtual machine or use another computer you own. Back when I had to learn networking in school we would ssh into two separate Linux boxes to test our code.

EDIT: Also to make sure you are receiving correctly you could make the sender and receiver both print out the packet data they receive. Or you could just have them print a simple string to say the packet was received.

You also might want to check out TCP rather than UDP if you are wanting a continuous stream. UDP just creates a datagram packet and sends it out on the network, whereas TCP creates a persistant connection between two hosts.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top