Java UDP message exchange works over localhost but not Internet? - java

Client A
import java.io.*;
import java.net.*;
import java.util.*;
public class ClientA
{
final private static int PORT = 5005; // arbitrarily assigned port to use
public static void main(String args[]) throws
IOException
{
DatagramSocket socket = new DatagramSocket(PORT); // create new connection on that port
while (true)
{
byte buffer[] = new byte[256]; // data buffer
DatagramPacket packet = new DatagramPacket(buffer, buffer.length); // new packet containing buffer
socket.receive(packet); // look for packet
String clientBMsg = new String(packet.getData()); // get data from received packet
InetAddress address = packet.getAddress(); // get address of received packet
System.out.println("ClientB at " + address + " says " + clientBMsg);
buffer = null;
String msgString = "I'm ClientA, vegetables are fun";
buffer = msgString.getBytes(); // put String in buffer
int port = packet.getPort(); // get port of received packet
packet = new DatagramPacket(buffer, buffer.length, address, port); // create new packet with this data
socket.send(packet); // send packet back containing new buffer!
System.out.println("Message Sent");
socket.close();
}
}
}
Client B
import java.io.*;
import java.net.*;
public class ClientB
{
final private static int PORT = 5005; // arbitrarily assigned port - same as server
public static void main(String args[]) throws
IOException {
// if (args.length == 0) { // requires host
// System.err.println
// ("Please specify host");
// System.exit(-1);
// }
// String host = args[0]; // user defined host
DatagramSocket socket = new DatagramSocket(); // open new socket
String host = "localhost";//"86.0.164.207";
byte message[] = new byte[256]; // empty message
String msgString = "Hello, I'm client B and I like trees";
message = msgString.getBytes(); // put String in buffer
InetAddress address = InetAddress.getByName(host); // determines address
System.out.println("Sending to: " + address); // tells user it's doing something
DatagramPacket packet = new DatagramPacket(message, message.length, address, PORT); // create packet to send
socket.send(packet); // send packet
System.out.println("Message Sent");
message = new byte[256];
packet = new DatagramPacket(message, message.length);
socket.receive(packet); // wait for response
String clientAreply = new String(packet.getData());
System.out.println("ClientA at " + host + " says " + clientAreply);
socket.close();
}
}
I don't understand why this works over localhost but when I put my IP address in, it just sends the message and nothing is received.
Can anyone point me in the right direction here?
Thank you!

You should use DatagramSocket's bind method to bind it to your internet interface, otherwise it only listens on 127.0.0.1 or localhost. Like this:
DatagramSocket socket = new DatagramSocket(null);
socket.bind(new InetSocketAddress(InetAddress.getByName("your.ip.add.ress"),5005);
In case you are behind your router then your should listen on the local IP address given to you by the router and use port forwarding to this address in your router settings.

I can suggest using Socket Test tool with TCP and UDP Sockets:
http://sockettest.sourceforge.net/
I used it to trouble shoot issues with a 2-way socket program. You can end-to-end test your link with two SocketTest programs and the compare results, etc. Very useful.

Related

How to make a TCP connection between two clients behind NAT of different networks?

I have a setup, where 2 pc's(let's say A and B) are behind NAT of each pubic IP. So they each have their own different private IP . I am using a server in between, which will interchange the IP Address and Port no. of A and B. They also exchange their internal Port no..!
So basically this is the setup.
Client A and B run the following code:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Clientnew {
public static void main(String[] args) throws Exception {
// prepare Socket
DatagramSocket clientSocket = new DatagramSocket();
for(int i = 1;i<10;i++){
// prepare Data
byte[] sendData = "Hello".getBytes();
// send Data to Serverc
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, InetAddress.getByName("27.251.62.27"), 7070);
clientSocket.send(sendPacket);
//send localip and local port to server
System.out.println("Sending Local info");
// InetAddress IPAddressLocal = clientSocket.getLocalAddress();
int PortLocal = clientSocket.getLocalPort();
String msgInfoOfClient1 = PortLocal+":PortLocal";
byte[] newData = msgInfoOfClient1.getBytes();
System.out.println(msgInfoOfClient1);
DatagramPacket sendLocalPacket = new DatagramPacket(newData, newData.length, InetAddress.getByName("27.251.62.27"), 7070);
clientSocket.send(sendLocalPacket);
// receive External Data ==> Format:"<External IP of other Client>-<External Port of other Client>"
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
clientSocket.receive(receivePacket);
// Convert Response to IP and Port
String response = new String(receivePacket.getData());
String[] splitResponse = response.split("-");
InetAddress External_IP = InetAddress.getByName(splitResponse[0].substring(1));
int External_Port = Integer.parseInt(splitResponse[1]);
// output converted Data for check
System.out.println("External IP: " + External_IP + " External PORT: " + External_Port);
// receive Internal Data ==> Format:"<Internal IP of other Client>-<Internal Port of other Client>"
DatagramPacket anotherPacket = new DatagramPacket(new byte[1024], 1024);
clientSocket.receive(anotherPacket);
// Convert Response to IP and Port
response = new String(anotherPacket.getData());
splitResponse = response.split(":");
// InetAddress Internal_IP = InetAddress.getByName(splitResponse[0].substring(1));
int Internal_Port = Integer.parseInt(splitResponse[0]);
// output converted Data for check
System.out.println(" Internal PORT: " + Internal_Port);
}
}
}
And the code on Server S is:-
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Servernew {
public static void main(String args[]) throws Exception {
DatagramSocket serverSocket2 = new DatagramSocket(6588);
// Waiting for Connection of Client1 on Port 7070
// ////////////////////////////////////////////////
// open serverSocket on Port 7070
DatagramSocket serverSocket1 = new DatagramSocket(7070);
for(int i= 1; i<10;i++){
System.out.println("Waiting for Client 1 on Port "
+ serverSocket1.getLocalPort());
// receive Data
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket1.receive(receivePacket);
// Get IP-Address and Port of Client1
InetAddress IPAddress1 = receivePacket.getAddress();
int port1 = receivePacket.getPort();
String FirstmsgInfoOfClient1 = IPAddress1 + "-" + port1 + "-";
System.out.println("Client1 External: " + FirstmsgInfoOfClient1);
// Get Message from Client
DatagramPacket anotherPacket = new DatagramPacket(new byte[1024], 1024);
serverSocket1.receive(anotherPacket);
// Decode the String
String response = new String(anotherPacket.getData());
String[] splitResponse = response.split(":");
// InetAddress LocalIP1 = InetAddress.getByName(splitResponse[0].substring(1));
int LocalPort1 = Integer.parseInt(splitResponse[0]);
// int LocalPort1 = Integer.parseInt(splitResponse[1]);
// String msgInfoOfClient1 = PortLocal+":PortLocal";
String SecondmsgInfoOfClient1 = LocalPort1+":LocalPort1";
System.out.println("Client1 Internal: " + SecondmsgInfoOfClient1);
// System.out.println(response);
// Waiting for Connection of Client2 on Port 6588
// ////////////////////////////////////////////////
// open serverSocket on Port 6588
// DatagramSocket serverSocket2 = new DatagramSocket(6588);
System.out.println("Waiting for Client 2 on Port "
+ serverSocket2.getLocalPort());
// receive Data
receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket2.receive(receivePacket);
// GetIP-Address and Port of Client1
InetAddress IPAddress2 = receivePacket.getAddress();
int port2 = receivePacket.getPort();
String FirstmsgInfoOfClient2 = IPAddress2 + "-" + port2 + "-";
System.out.println("Client2 External:" + FirstmsgInfoOfClient2);
// Get Message from Client
anotherPacket = new DatagramPacket(new byte[1024], 1024);
serverSocket2.receive(anotherPacket);
// Decode the String
response = new String(anotherPacket.getData());
splitResponse = response.split(":");
// InetAddress LocalIP1 = InetAddress.getByName(splitResponse[0].substring(1));
int LocalPort2 = Integer.parseInt(splitResponse[0]);
// int LocalPort1 = Integer.parseInt(splitResponse[1]);
//
String SecondmsgInfoOfClient2 = LocalPort2+":LocalPort2";
System.out.println("Client2 Internal: " + SecondmsgInfoOfClient2);
// Send the Information to the other Client
/////////////////////////////////////////////////
// Send Information of Client2 to Client1
serverSocket1.send(new DatagramPacket(FirstmsgInfoOfClient2.getBytes(),
FirstmsgInfoOfClient2.getBytes().length, IPAddress1, port1));
serverSocket1.send(new DatagramPacket(SecondmsgInfoOfClient2.getBytes(),
SecondmsgInfoOfClient2.getBytes().length, IPAddress1, port1));
// Send Infos of Client1 to Client2
serverSocket2.send(new DatagramPacket(FirstmsgInfoOfClient1.getBytes(),
FirstmsgInfoOfClient1.getBytes().length, IPAddress2, port2));
serverSocket2.send(new DatagramPacket(SecondmsgInfoOfClient1.getBytes(),
SecondmsgInfoOfClient1.getBytes().length, IPAddress2, port2));
System.out.println("-----------------\n");
System.out.println("---------------------");
}
//close Sockets
serverSocket1.close();
serverSocket2.close();
}
}
And the Output is that they are exchanging their Internal and External Ports and Public IP perfectly well.
So the Question is How do I use this information to open a TCP connection between A and B? How do I implement a TCP Punch hole using Java?
P.S: It is utmost necessary to be a TCP connection and that I use Java to do so.
Open two ServerSocket on S, accepting connections from each of A and B (port 62000 and 31000 respectively). When accept in each case returns a Socket instance then cross the InputStream and OutputStream of each one into one another using PipedOutputStream and PipedInputStream. You'll need to have a thread for each.

Java UDP Connection

I'm using Netbeans IDE trying to make a UDP connection between client and server, it's a simple program that UDPClient send a String to UDPServer and the server capitalize the string and sends it back to the client.I made the client side and server side in a separated projects.
my class code for the client UDPClient :
package udpclient;
import java.io.*;
import java.net.*;
public class UDPClient {
public static void main(String[] args) throws IOException{
//get input from user
BufferedReader user_in = new BufferedReader(
new InputStreamReader(System.in));
//create udp socket connection
DatagramSocket socket = new DatagramSocket();
//creat buffers to process data
byte[] inData = new byte[1024];
byte[] outData = new byte[1024];
//get ip destination wanted
InetAddress IP = InetAddress.getByName("localhost");
//read data from user
System.out.println("Enter Data to send to server: ");
outData = user_in.readLine().getBytes();
/*
* make pkts for interaction
*/
//send pkts
DatagramPacket sendPkt = new DatagramPacket(outData, outData.length, IP, 9876);
socket.send(sendPkt);
//receive pkts
DatagramPacket recievePkt = new DatagramPacket(inData, inData.length);
socket.receive(recievePkt);
System.out.println("Replay from Server: "+recievePkt.getData());
}
}
and my server side class UDPServer:
package udpserver;
import java.io.*;
import java.net.*;
public class UDPServer {
public static void main(String[] args) throws IOException{
// TODO code application logic
//connection
DatagramSocket socket = new DatagramSocket();
//pkt buffers
byte[] inServer = new byte[1024];
byte[] outServer = new byte[1024];
//receive pkt
DatagramPacket rcvPkt = new DatagramPacket(inServer,inServer.length);
socket.receive(rcvPkt);
//display receive
System.out.println("Packet Received!");
//retrive pkt info to send response to same sender
InetAddress IP = rcvPkt.getAddress();
int port = rcvPkt.getPort();
//process data
String temp = new String(rcvPkt.getData());
temp = temp.toUpperCase();
outServer = temp.getBytes();
//send response packet to sender
DatagramPacket sndPkt = new DatagramPacket(outServer, outServer.length, IP, port);
socket.send(sndPkt);
}
}
make in count that the program runs normally and outputs no error. the server doesn't receive the packet at all , it didn't interact with the client. why does that happened ?
You haven't specified any listening port in your server so the server listen on a random available port.
Try with this on server side
DatagramSocket socket = new DatagramSocket(9876);
The problem is that your server code doesn't specify a port - it will listen to a random available port, whereas the client is sending to 9876. To correct this, use:
DatagramSocket socket = new DatagramSocket(9876, InetAddress.getByName("localhost"));
(If you're on a linux system) I'd highly recommend using netstat to debug this kind of code:
netstat -ln | grep 9876
will tell you if a process is listening to port 9876.
Another useful tool is netcat, which can be used to send and receive TCP and UDP:
nc -u localhost 9876
allows you to send messages over UDP to the server.
In your client code, you also need to turn the received bytes back into a string to get meaningful output.

In Java: UDP based Client/Server not giving the expected output

I have written a simple Client/Server code in Java, in which a client sends a message to server (which is displayed on Server's Standard Output) and then server also sends a message (which is displayed on Client's Standard Output). Code for Client and Server is given below:
Client.java
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args)throws Exception {
DatagramSocket socket = new DatagramSocket ();
InetAddress address = InetAddress.getByName("127.0.0.1");
DatagramPacket packet = null;
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
byte[] buf = new byte[256];
String msg = stdIn.readLine();
packet = new DatagramPacket(buf, buf.length, address, 4445);
socket.send(packet);
// get response
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
// display response
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println("Server says: " + received);
socket.close();
}
}
And below is Server.java
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args)throws Exception {
DatagramSocket socket = new DatagramSocket(4445);
byte[] buf = new byte[256];
// receive client's message
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
// display client's message
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println("Client says: " + received);
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String msg = stdIn.readLine();
buf = msg.getBytes();
// send the response to the client at "address" and "port"
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(buf, buf.length, address, port);
socket.send(packet);
}
}
The code compiles and runs successfully, but the output does not come as expected. The message sent by Client is NOT displayed at Server, but Server's message is successfully displayed at Client.
So can anyone kindly tell what can be the problem?
You never populate the packet with any useful data:
byte[] buf = new byte[256];
String msg = stdIn.readLine();
packet = new DatagramPacket(buf, buf.length, address, 4445);
socket.send(packet);
You've just posted a byte array with 256 bytes, all of which are 0. You've ignored msg entirely. Perhaps you wanted:
String msg = stdIn.readLine();
byte[] buf = msg.getBytes(StandardCharsets.UTF_8);
packet = new DatagramPacket(buf, buf.length, address, 4445);
socket.send(packet);
That's similar to the code you're using in the server, after all... except that I'm using UTF-8 explicitly, which I would recommend you do everywhere, when converting between byte[] and String.

Java why isn't the socket listening on the local port I specified in the constructor / bound to?

I'm having a weird problem, let's consider the following code :
import java.net.*;
import java.util.Enumeration;
public class Main{
public static void main(String args[]) throws Exception {
Inet4Address myIp = (Inet4Address)Inet4Address.getByName(Main.getLanIp());
InetSocketAddress myAddr = new InetSocketAddress(myIp, LocalportNumber);
if(myIp == null){
throw new Exception();
}
DatagramSocket socket = new DatagramSocket(myAddr);
socket.setReuseAddress(true);
InetAddress IPAddress = InetAddress.getByName("239.xxx.xxx.xxx");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = "PAYLOAD";
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, distantPortNumber);
DatagramPacket receivePacket = new DatagramPacket(receiveData, 1024);
socket.send(sendPacket);
System.out.println("Packet sent");
socket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
socket.close();
}
static public String getLanIp() throws SocketException{
InetAddress inet_addr = null;
NetworkInterface cur = null;
for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();){
cur = interfaces.nextElement();
try {
if (cur.isLoopback())
{
continue;
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("interface " + cur.getName());
for (InterfaceAddress addr : cur.getInterfaceAddresses()){
inet_addr = addr.getAddress();
if ( !( inet_addr instanceof Inet4Address)){
continue;
}
System.out.println(" address: " + inet_addr.getHostAddress() + "/" + addr.getNetworkPrefixLength());
System.out.println(" broadcast address: " + addr.getBroadcast().getHostAddress());
}
}
return inet_addr.getHostAddress();
}
}
Execution trace :
"""
interface eth0
address: 192.168.0.20/24
broadcast address: 192.168.0.255
Packet sent
"""
When I run the preceding code, a packet is sent, the server answers but I still block on the receive method, I can see the incoming packet on wireshark reaching my computer. But when I try a : "netstat -npl", I see a java process listening on the port localPort. I tried a "nc -vvv -u 9393" from remote (lan) and then typed random sentences ... Nothing happened. I tried the same on local (with my external IP, with my loopback IP), same problem. Is there a list of known problems which could block the received udp packets between the kernel and the jvm ?
I found my problem : my iptable firewall ... I was blocking all the incoming traffic which was not an answer to my outgoing traffic. That's why I saw the traffic on wireshark but I didn't reached the java socket...
So the solution was to open my firewall -_-"

multicastSocket doesn't receive packets

I am working on a simple audio streamer with multicast. I wrote serer and client on the same machine, so I worked with localhost and multicast-groups. The system works on one machine but when I tried to use another PC as the server, I can't get them to connect. Here is the situation:
The client first knocks on a tcp-server which lets the client know the multicasting-group IP an port. After this, the client starts listining to the address via multicastSocket.receive();.
Here are the important bits from the system:
(I left out the exceptions and other non-important stuff in the following code)
Server
Important to know is that the "LAN-Connection" is the name of my network interface on the servers system.
int multicastPort = 8888;
InetAddress multicastIP = InetAddress.getbyName("228.5.6.7");
InetSocketAddress multicastAddress = new inetSocketAddress( multicastIP, multicastPort );
NetworkInterface multicastInterface = NetworkInterface.getByName( "LAN-Connection" );
MulticastSocket multicastSocket = new MulticastSocket( multicastPort );
multicastSocket.joinGroup( multicastAddress, multicastIP);
while(true) {
byte [] buffer = audioIn.readBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, multicastIP, multicastPort);
multicastSocket.send(packet );
}
Client
The client requests the multicast-IP and Port from the server. (a tcp-server-thread handles this) Like with the server "LAN-Connection" is the name of the clients network interface.
int multicastPort = server.request("port");
String multicastIP_String = server.request("IP");
InetAddress multicastIP = InetAddress.getbyName(multicastIP_String );
InetSocketAddress multicastAddress = new inetSocketAddress( multicastIP, multicastPort );
NetworkInterface multicastInterface = NetworkInterface.getByName( "LAN-Connection" );
MulticastSocket multicastSocket = new MulticastSocket( multicastPort );
multicastSocket.joinGroup( multicastAddress, multicastIP);
while(true) {
byte [] buffer = new byte[2048];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
multicastSocket.receive(packet);
}
The TCP connection for requesting / sending the multicast IP and port works. An application called CurrPorts also tells me, that the correct ports get reserved, however, with wireshark, I can't find any packets sended / received neither on the clients system nor the server system. (I watched port 88 but there is no traffic,...)
Both PCs are connected to one router(D-Link DIR-635) and i guess I would have noticed If multicasting woudl be blocked by the router, right?
What am I missing? Shoudl I try different ports or IPs or could something block the packets? I only use windows firewall and I even turned this thing off for a test.
Here is a running example. I have no problem running this on the same machine but when I run the server on my laptop in the same network, nothing works.
Server
package multicastserver;
import java.net.*;
public class MulticastServer {
public static void main(String[] args) {
int multicastPort = 8888;
try {
InetAddress multicastIP = InetAddress.getByName("228.5.6.7");
InetSocketAddress multicastAddress = new InetSocketAddress( multicastIP, multicastPort );
NetworkInterface multicastInterface = NetworkInterface.getByName( "LAN-Verbindung" );
MulticastSocket multicastSocket = new MulticastSocket( multicastPort );
multicastSocket.joinGroup(multicastAddress, multicastInterface);
int counter = 0;
while(true) {
String message = "This is server, packet nr. " + counter;
counter++;
byte [] buffer = message.getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, multicastIP, multicastPort);
multicastSocket.send(packet);
System.out.println("Sended: " + message);
Thread.sleep(500);
}
} catch (Exception e) {
System.out.println(e);
return;
}
}
}
Client
package multicastclient;
import java.net.*;
public class MulticastClient {
public static void main(String[] args) {
int multicastPort = 8888;
try {
InetAddress multicastIP = InetAddress.getByName("228.5.6.7");
InetSocketAddress multicastAddress = new InetSocketAddress( multicastIP, multicastPort );
NetworkInterface multicastInterface = NetworkInterface.getByName( "LAN-Verbindung" );
MulticastSocket multicastSocket = new MulticastSocket( multicastPort );
multicastSocket.joinGroup(multicastAddress, multicastInterface);
while(true) {
byte [] buffer = new byte[40];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
multicastSocket.receive(packet);
buffer = packet.getData();
String message = new String(buffer, "UTF-8");
System.out.println("Received: " + message);
}
} catch (Exception e) {
System.out.println(e);
return;
}
}
}

Categories