No address in DatagramPacket - java

I am attempting to add a multiplayer form to a simple pong game, but when I try to start the DatagramPacket and try to read the IP and port it says the ip is null and the port is -1. Does anyone know why it would be doing this? I thought maybe it was because the socket hadn't recieved the packet yet, but when I look I saw that all code after socket.recieve(packet) isn't running.
Code where I start the server:
public GameServer(PongEngine engine) {
this.engine = engine;
try {
this.socket = new DatagramSocket(4269);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
System.out.println(packet.getAddress() + ":" + packet.getPort());
try {
socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
String message = new String(packet.getData());
if(message.trim().equalsIgnoreCase("ping")) {
System.out.println("CLIENT[" + packet.getAddress() + ":" + packet.getPort() + "] > " + message);
sendData("pong".getBytes(), packet.getAddress(), packet.getPort());
}
}
}

DatagramPacket's getAddress returns the IP address of the machine to which this datagram is being sent or from which the datagram was received.
In the first System.out.println you have just created the object, but have not done any network I/O with it.
Then you ignore the exception and just try to work with the datagram. If there was an I/O error, it's likely that the datagram was not initialized and hence still has IP address null and port -1.
If nothing happens after socket.receive() I'd assume the call is blocked, waiting for a packet to come in. Do you actually run the client that connects to your server code?

To add to Roberts answer, your code is simply out of order. Once you have that fixed then you can address why you might not be recieving a packet form the other PC like ccarton suggested.
Try this, and note the two comments
public void run() {
while(true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
//Wait for packet (The code will not move on until a packet is received or there is an error)
System.out.println("Waiting for packet");
socket.receive(packet);
//Move your socket/port info after receiving a packet so you don't get null or -1
System.out.println("Packet received: "+ packet.getAddress() + ":" + packet.getPort());
//Move your code inside try, rather than after
String message = new String(packet.getData());
if(message.trim().equalsIgnoreCase("ping")) {
System.out.println("CLIENT[" + packet.getAddress() + ":" + packet.getPort() + "] > " + message);
sendData("pong".getBytes(), packet.getAddress(), packet.getPort());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Now do you still get the same issues?

Related

Keep Alive Socket between Java client and VB Server

I've created program to send and get data from client to server and for client i used java and server I used Visual Basic so how to set the connection between client and server is keep alive in a client(java) side?
this is the code from client :
public static void Client(){
String print = "";
String dataDB = "Hello server, From Client";
try(Socket clientSocket = new Socket("localhost", port)){
clientSocket.getOutputStream().write(dataDB.getBytes("ASCII"));
while (clientSocket.getInputStream().available() == 0) {
Thread.sleep(100L);
}
byte[] data = new byte[clientSocket.getInputStream().available()];
int bytes = clientSocket.getInputStream().read(data, 0, data.length);
print = new String(data, 0, bytes, "ASCII");//.substring(4,bytes);
while(print.length()>0){
System.out.println("From Server : "+print);
}
}catch (IOException ex){
System.out.println("I/O error: " + ex.getMessage());
}catch(InterruptedException ie){
System.out.println("error: " + ie.getMessage());
}catch(Exception e){
System.out.println("error: " + e.getMessage());
}
}
The Java client is a console application, just sent and get data from server i tried to used clientSocket.setKeepAlive(true); but is not working.

UDP Program Packet Loss Tracing [duplicate]

This question already has answers here:
How to detect that UDP packet has been lost? (C#)
(5 answers)
Closed 2 years ago.
For a reliable connection you have to use TCP.
However, I would like to know if there is a way to modify my code so that I can check for lost packets in UDP
try {
DatagramSocket socket = new DatagramSocket(5000);
while(true) {
byte[] buffer = new byte[50];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
System.out.println("Text received is: " + new String(buffer, 0, packet.getLength()));
String returnString = "echo: " + new String(buffer, 0, packet.getLength());
byte[] buffer2 = returnString.getBytes();
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(buffer2, buffer2.length, address, port);
socket.send(packet);
}
} catch(SocketException e) {
System.out.println("SocketException: " + e.getMessage());
} catch(IOException e) {
System.out.println("IOException: " + e.getMessage());
}
}
Since the transport protocol does not provide facilities, the application protocol needs to do so.
You could for example make the sender add a sequence number into each message, and the receiver would then know that a datagram had been lost, or (also possible) duplicated.
That lets you detect loss, but does nothing to allow you to recover from it.
You'd need in the receiver to track expected sequence numbers per sender, of course.

Java UDP Client Not Receiving Packets

I've made a java application which uses UDP and I can't seem to receive packets outside LAN when hosting on my computer. I tried putting my application on a Hosted Server and it seemed to work (receives packet).
What is causing this to happen? I want it to work on my computer as well.
CLIENT:
try {
this.socket = new DatagramSocket(2500);
} catch (SocketException e1) {
System.out.println("Could not establish connection");
return;
}
while(true){
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try{
socket.receive(packet);
}catch(IOException e){
System.out.println("Connection close");
break;
}
System.out.println("RECEIVED " + new String(packet.getData()));
}
SERVER:
try {
this.socket = new DatagramSocket(25860);
} catch (SocketException e) {
e.printStackTrace();
}
try {
byte[] data = datas.getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 2500);
socket.send(packet);
}catch(IOException e) {
}
System.out.println("Sent " + ipAddress.getHostAddress() + ":" + port + " " + new String(datas));
IP Address is correct, it exactly prints out the same IP as my CLIENT. However I'm still not receiving.
If it works in one computer (single) and not on the other try checking the firewall, UDP connections should be allowed in your computer.

UDP Holepunching behind NAT

I am trying to implement a simple sketch of UDP-Holepunching in Java to test it's concept and use it in my C/C++ application later on.
Concept:
As from Wikipedia I understood the concept as this:
Let A and B be clients behind an undefined networkstructure and C a well-known public reachable server.
A sends a packet to the server C, the server saves it's IP-Address and port. C will get the public IP-Address of A's NAT. Doing this, the NAT in front of A will create a route that will pass all packets on this port to A.
B does the same as A, sending a packet to server C, which will then save it's Address and port, B's NAT creates a route and so on.
At this point, C knows both address and port of each client. C will send the address and port of B to A and from A to B.
A sends a packet to B which will be rejected by B's NAT, but doing so will open a "hole" in A's NAT, letting further packets from B pass.
B sends a packet to A which will reach A, as a "hole" was "punched" before. Doing so will also open a "hole" in B's NAT, letting further packets from A pass.
The holepunch is now done and A and B should be able to communicate with each other P2P
This is all working well over localhost (which is not such a big surprise), but in a real-world-example this fails.
Problem:
A and B are both able to connect to server C, which gets their packets, stores their address and port and transmits it to the other client.
But at this point it fails. A and B are not able to communicate with each other.
So I am asking myself where I did wrong. I spent days searching for working examples in google and stackoverflow but all I stumbled upon is the suggestion to use STUN which is not what I want.
Implementation:
Below I will post my sketch in Java, as I do not know whether I have a problem with my concept or my implementation.
This is the code of the server:
public class Server
{
public static void main(String[] args)
{
int port1 = 0, port2 = 0;
String address1 = null, address2;
byte[] bytes = new byte[1024];
try
{
System.out.println("Server waiting");
DatagramSocket ds = new DatagramSocket(789);
while(!Thread.interrupted())
{
DatagramPacket p = new DatagramPacket(bytes, bytes.length);
ds.receive(p);
if(port1 == 0)
{
port1 = p.getPort();
address1 = p.getAddress().getHostAddress();
System.out.println("(1st) Server received:" + new String(bytes) + " from " + address1 + " on port " + port1);
}
else
{
port2 = p.getPort();
address2 = p.getAddress().getHostAddress();
System.out.println("(2nd) Server received:" + new String(bytes) + " from " + address1 + " on port " + port1);
sendConnDataTo(address1, port1, address2, port2, ds);
sendConnDataTo(address2, port2, address1, port1, ds);
}
}
ds.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void sendConnDataTo(String a1, int p1, String a2, int p2, DatagramSocket ds)
{
byte[] bA, bP;
bA = a1.getBytes();
bP = Integer.toString(p1).getBytes();
DatagramPacket pck;
try
{
pck = new DatagramPacket(bA, bA.length, InetAddress.getByName(a2), p2);
ds.send(pck);
pck = new DatagramPacket(bP, bP.length, InetAddress.getByName(a2), p2);
ds.send(pck);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Please note, that this is just some sketch, no real application. The server should only receive packets from two clients, save their address and port and pass it to the other client.
This is the code of the client:
public class Client
{
private DatagramSocket socket;
private int init = 0;
private String target;
private int port;
public Client()
{
try
{
socket = new DatagramSocket();
}
catch(SocketException e)
{
e.printStackTrace();
}
Thread in = new Thread()
{
public void run()
{
while(true)
{
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
try
{
socket.receive(packet);
bytes = Arrays.copyOfRange(bytes, 0, packet.getLength());
String s = new String(bytes);
System.out.println("Received: " + s);
if(init == 0)
{
target = s;
System.out.println("Target: " + target);
init++;
}
else if(init == 1)
{
port = Integer.parseInt(s);
System.out.println("Port: " + port);
init++;
}
else System.out.println(new String(bytes));
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
};
in.start();
connectToSupervisor();
}
private void connectToSupervisor()
{
byte[] bytes = new byte[1024];
System.out.println("Greeting server");
System.arraycopy("EHLO".getBytes(), 0, bytes, 0, 4);
try
{
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 789);
socket.send(packet);
System.out.println("Greetings sent...");
}
catch(IOException e)
{
e.printStackTrace();
}
send();
}
private void send()
{
while(init != 2)
{
try
{
Thread.sleep(20L);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("Init completed!");
while(true)
{
byte[] b2 = "Hello".getBytes();
byte[] b1 = new byte[6];
System.arraycopy(b2, 0, b1, 0, b2.length);
try
{
DatagramPacket packet = new DatagramPacket(b1, b1.length, InetAddress.getByName(target), port);
socket.send(packet);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
new Client();
}
}
The client will just send a packet to the server, listen for packets from it, grab the connection-data from the other client and will then continuously send packets containing "Hello" to it.
I am sorry for the long code but I wanted to keep it complete.
I would be glad if anyone of you could point me to the mistakes I am doing, explain me why this is not working, give me a working example or at least point me to an alternative.
Your code seems to be correct. I tested your code and it works fine. The concept is also correct. But please check whether both the clients you run are within same NAT device or different NAT devices. If your are running both the clients under same NAT device then it may not work because not all NAT devices support hair pinning i.e, both clients send packets to NAT's external IP which needs to be passed to itself. For more information refer this link:
https://www.rfc-editor.org/rfc/rfc4787#section-6
Given your conceptual outline, I think there is an issue at point 4. Although A punches a hole through its own NAT, when B attempts to reach this hole it is unaware of the port on A's NAT (or more correctly/commonly - NAPT) and hence A's NAT drops the packet when B attempts to communicate.
Just a note for those following this great post, notice that in the server side, the second UDP packet received is announced as: System.out.println("(2nd) Server received:" + new String(bytes) + " from " + address1 + " on port " + port1); It should be System.out.println("(2nd) Server received:" + new String(bytes) + " from " + address2 + " on port " + port2); Its no big deal since its only an informative message, but it made me lose some time just wondering how the hell on earth the router was giving the same port to 2 different communications :P

TCP/IP Sending request and getting response

I am Working on TCP/IP in Java. First, I read TCP/IP and understand how it's working.
What i Need:-
Ok, Now i want to implement it in java. I am trying to Send some input in request to specific port/IP from my IP. and need to get response.
I don't understand how to implement it.
Here is my Input:
Destination IP
Destination Port
Input(String or Anything)
Here is my code which i use for Client.
try {
socket = new Socket("localhost", port);
}
catch(Exception e) {
System.out.println("Error connectiong to server:" + e);
return;
}
System.out.println("Connection accepted " +
socket.getInetAddress() + ":" +
socket.getPort());
/* Creating both Data Stream */
try
{
Sinput = new ObjectInputStream(socket.getInputStream());
Soutput = new ObjectOutputStream(socket.getOutputStream());
}
catch (IOException e) {
System.out.println("Exception creating new Input/output Streams: " + e);
return;
}
// now that I have my connection
String test = "aBcDeFgHiJkLmNoPqRsTuVwXyZ";
// send the string to the server
System.out.println("Client sending \"" + test + "\" to serveur");
try {
Soutput.writeObject(test);
Soutput.flush();
}
catch(IOException e) {
System.out.println("Error writting to the socket: " + e);
return;
}
// read back the answer from the server
String response;
try {
response = (String) Sinput.readObject();
System.out.println("Read back from server: " + response);
}
catch(Exception e) {
System.out.println("Problem reading back from server: " + e);
}
try{
Sinput.close();
Soutput.close();
}
Please give me some hint or reference.
Creating Scoket
go through this will help you.
if you are implementing Sockets, you need to use ServerSocket class to create the ServerSocket . Then Socket class to request the create the connection between Client and Sever.

Categories

Resources