简体   繁体   中英

Sending Datagram Packets in Java

I am writing a program to send an integer (variable called intToSend) over a network using UDP. I run the program on two machines on the same network, one after the other. I thought that after running them both, the first one to be run would open a message box with the sent integer, but this doesn't happen. Both programs wait for a packet to be received as shown by "Waiting..." being printed to the console. I have the program ask for the destination ip to be input to the console. Then after that, the createSocket method is called, followed by sendData and then receiveData.

Here is the code:

package main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Scanner;

import javax.swing.JOptionPane;

public class Main {

    Scanner s = new Scanner(System.in);
    PrintStream o = System.out, e = System.err;

    InetAddress thisAddr, destAddr;
    DatagramSocket socket;

    int port = 1729, intToSend = 8;

    boolean running = true;

    public static void main(String[] args) {
        new Main();
    }

    private Main() {
        try {
            thisAddr = InetAddress.getLocalHost();
            System.out.println("Internal IP: " + thisAddr.getHostAddress().toString());
            System.out.println("External IP: " + getIp());
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            destAddr = InetAddress.getByName(getDestIp());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        createSocket();
        sendData();
        receiveData();
    }

    private void receiveData(){
        byte[] receiveBuffer = new byte[1024];
        DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
        while(true){
            System.out.println("Waiting...");
            try {
                socket.receive(receivePacket);
            } catch (IOException e) {
                e.printStackTrace();
            }
            String receivedText = new String(receivePacket.getData());
            JOptionPane.showMessageDialog(null, receivedText);
        }
    }

    private void sendData(){
        byte[] dataToSend = String.valueOf(intToSend).getBytes();
        DatagramPacket packet = new DatagramPacket(dataToSend, dataToSend.length, destAddr, port);
        try {
            socket.send(packet);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void createSocket(){
        try {
            socket = new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }


    public static String getIp() throws IOException{
        URL whatismyip = new URL("http://icanhazip.com");
        BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
        return in.readLine();
    }

    private String getDestIp() {
        String temp;
        o.println("What is the other user's ip?");
        temp = s.nextLine();
        return temp;
    }
}

This code works for me. If I input the target IP as the local machine's IP then I get the popup. If I input another machine on the network I also get the popup. My guess would be that either one of your machines has a firewall running that is blocking the incoming UDP packet, or your machines have multiple network interfaces and the IP you detect is not the one that is on the same network as the other machine.

In the former case you can disable the firewall (not a good idea if your machines are not behind a router with a firewall or are on a network which you don't have full control over) or open the specific port for incoming and outgoing UDP on both machines.

In the latter case you want to look out for the IPs presented on both machines being on the same subnet (the first three numbers being the same in the case if IPv4) eg both starting with 192.168.1. or similar.

When you do get your packet through you will probably get a very long popup window because you allocate a 1024 byte array and put the string at the start of that array but then convert the entire 1024 byte array into a string which may include various stuff off the end of the first N bytes you wrote the int into.

There are various ways to resolve that but this but a simple way to be able to pack a bunch of data into a packet and then read it back reliably is to use ByteArrayInput/OutputStreams and DataInput/OutputStreams:

//Sending side
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
dout.writeInt(N);  //this will write 4 bytes
byte[] packetData = bout.toByteArray();

//Receiving side
byte[] packetBuffer = ...;
ByteArrayInputStream bin = new ByteArrayInputStream(packetBuffer);
DataInputStream din = new DataInputStream(bin);
int N = din.readInt();  //This will read only the first 4 bytes, and use the same marshalling as DataOutputStream to produce a consistent value, even if the integer value is something exceptional like infinity or NaN.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM