Pergunta

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!

Foi útil?

Solução

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>

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top