Here is my setup: On my home network a server is running on port SERVER_PORT. A port forwarding rule has been added to the router such that all incoming connections to SERVER_PORT will reach the server's machine. Somewhere else on the internet there exists a client who tries to send a UDP packet to the server and receive a packet back.
The server will receive the connection on SERVER_PORT but will send a packet back from a socket bound to a different (random) port.
The idea is emulating a listener socket just like the one used for TCP, and for each new connection allocating a new socket.
I have tested my program with clients that are connected to my home network, and outside the home network (cellular). The program didn't work either way.
The program does work though if I send a packet back using the server's original socket (the one that is bound to SERVER_PORT).
I am assuming this has something to do with my router's NAT table but I can't quite figure out the details.
My question is how can a packet be sent back from a different socket, other than the one that had been used for previous packets, and would I have had the same issue if the server was directly connected to the internet?
I wrote a small java program to demonstrate the issue:
Here is the server's code:
//create both sockets and a buffer
DatagramSocket serverSocket1 = new DatagramSocket(SERVER_PORT);
DatagramSocket serverSocket2 = new DatagramSocket();
byte[] buffer = new byte[512];
//receive a packet from serverSocket1
DatagramPacket packet1 = new DatagramPacket(buffer, buffer.length);
serverSocket1.receive(packet1);
System.out.println("received packet from: address = " + packet1.getAddress() + ", port = "+ packet1.getPort());
//send a packet from serverSocket2
DatagramPacket packet2 = new DatagramPacket(buffer, buffer.length, packet1.getAddress(), packet1.getPort());
serverSocket2.send(packet2);
System.out.println("sent packet back");
Here is the client's code: (note: SERVER_ADDRESS is set to my public ip)
//create a socket for the client and a buffer
DatagramSocket clientSocket = new DatagramSocket();
byte[] buffer = new byte[512];
//send packet1
DatagramPacket clientPacket1 = new DatagramPacket(buffer, 0, buffer.length, InetAddress.getByName(Server.SERVER_ADDRESS), Server.SERVER_PORT);
clientSocket.send(clientPacket1);
System.out.println("sent packet");
//receive packet2
DatagramPacket clientPacket2 = new DatagramPacket(buffer, buffer.length);
clientSocket.receive(clientPacket2);
System.out.println("received packet from: address = " + clientPacket2.getAddress() + ", port = "+ clientPacket2.getPort());
After running first the server and the the client I get the following output:
server:
received packet from: address = /107.107.56.147, port = 29098
sent packet back
client:
sent packet
Related
I'm running Kannel and Smppsim on a virtual machine and sending SMPP packets through them. I see the packets on Wireshark, but when I try to capture them with a datagram packet in java I receive nothing.
Here's my code:
DatagramSocket ds = new DatagramSocket(2775);
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, 1024);
ds.receive(dp);
String str = new String(dp.getData(), 0, dp.getLength());
System.out.println(str);
ds.close();
I was doubtful about the port number so I also tried port 60720.
and here's an example of the packet I'm receiving on Wireshark:
I don't know what I'm doing wrong. and I'm not even sure that is the right way to capture smpp packets. Can someone help me please?
I have a situation like a Client1 sends data to client2 and from there the data is sent to a Server.Now from the server the data is sent to other multiple clients.
So,now when Client1 is connected to client2 and after sending some
data if the client1 disconnects how to know that the client1 is
disconnected in client2?
My Client1 code snippet is:
InetAddress address = InetAddress.getByName(ipAddress);
MulticastSocket socket = new MulticastSocket(port);
socket.joinGroup(address);//join a Multicast group and send the group salutations
byte[] data;
System.out.print("Enter data: ");
String str = (br.readLine());
DatagramPacket packet;
//send the packet
data = new byte[1024];
data = str.getBytes();
packet = new DatagramPacket(data,str.length(),address,port);
socket.send(packet);
My Client2 code snippet is:
InetAddress address = InetAddress.getByName(ipAddress);
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data,data.length);
MulticastSocket socket = new MulticastSocket(port);
socket.joinGroup(address);//join a Multicast group and send the group salutations
// receive the packets
socket.receive(packet);
str = new String(packet.getData(),0,packet.getLength());
System.out.println(ipname+" with portnumber "+port + " sent : "+str);
Now, if client1 gets connected to client2 and after some time it disconnects how to know that client1 got disconnected in client2?
I have already used isConnected(), isbound(), isClosed() and also isReachable(int timeout) methods. But none of them helped me.
The JavaDoc forDatagramPacket says:
Datagram packets are used to implement a connectionless packet
delivery service.
A connectionless protocol doesn't have a connection that can be closed. If you're building your own protocol on top of UDP/DatagramPacket, make it part of your protocol to 'close' the session.
I have made a UDP server. It is working well but the problem is, It only accepts the client request once and gives response but on sending the 2nd request it does not replies to the client and also doesnot receives the message.
Here is my code....... I am unable to troubleshoot this
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
DatagramSocket socket = new DatagramSocket(SERVERPORT,
serverAddr);
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
updatetrack("Server: Receiving\n");
socket.receive(packet);
updatetrack("Server: Message received: '"
+ new String(packet.getData()) + "'\n");
updatetrack("Server: Succeed!\n");
updatetrack("I want to send the data to you .......");
byte[] sbuff;
sbuff = ("opSERVERSTARTED").getBytes();
socket.send(new DatagramPacket(sbuff, sbuff.length, packet
.getAddress(), packet.getPort()));
Your code implies that you only want to receive one packet.
If you want to receive more packets, you have to do that in a loop and handle the runtime of the loop by a defined stop criteria.
socket.receive(packet); I think this code must be in a while loop, so it can accept more than one client. Something like this:
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
DatagramSocket socket = new DatagramSocket(SERVERPORT,
serverAddr);
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
while (someCondition) {
updatetrack("Server: Receiving\n");
socket.receive(packet);
updatetrack("Server: Message received: '"
+ new String(packet.getData()) + "'\n");
updatetrack("Server: Succeed!\n");
updatetrack("I want to send the data to you .......");
byte[] sbuff;
sbuff = ("opSERVERSTARTED").getBytes();
socket.send(new DatagramPacket(sbuff, sbuff.length, packet
.getAddress(), packet.getPort()));
}
I am not sure about the end of the curly brackets, I am not familiar with UDP server. You can move it to where the repeating code ends. Hope this helps!
This is my udp_broadcast server code where iam listening on 0.0.0.0
try{
socket = new DatagramSocket (7777,InetAddress.getByName("0.0.0.0"));
socket.setBroadcast(true);
while(true)
{
System.out.println(getClass().getName()+"ready recieve broadcast packets!");
//recieve a packet
byte[] recvBuf = new byte[15000];
DatagramPacket packet = new DatagramPacket(recvBuf,recvBuf.length);
socket.receive(packet);
System.out.println(getClass().getName() +"packet recieved from :" +packet.getAddress().getHostAddress());
System.out.println("data is "+new String(packet.getData()));
String message = new String(packet.getData()).trim();
if(message.equals("p2p_project_node"))
{
byte [] senddata = "I_found_you_did_YOU".getBytes();
DatagramPacket sendpacket= new DatagramPacket(senddata,senddata.length,packet.getAddress(),packet.getPort());
socket.send(sendpacket);
System.out.println("packet sent to "+sendpacket.getAddress().getHostAddress());
}
}
}
on client side iam broadcasting packet 255.255.255.255 so that i get a reply from server
eventually and i endup in getting server ip address
udp_client_side code
try {
c = new DatagramSocket();
c.setBroadcast(true);
byte [] sendData = "p2p_project_node".getBytes();
//this is broadcasting to 255.255.255.255a
try{
DatagramPacket sendPacket = new DatagramPacket(sendData,sendData.length,InetAddress.getByName("255.255.255.255"),7777);
c.send(sendPacket);
System.out.println("rewuest sent to 255.255.255.255");
}
catch(Exception e) {
System.out.println("exception 255.255" +e);
}
on the server side iam getting error saying that
Exception java.net.BindException "Address already in use :cannot bind"
where am i going wrong if someone could help me it would be great Thanks in advance
The address is already in use. You cannot bind your socket to that address. Some other process already has a UDP socket bound to that poet. Possibly a previous instance of your own program.
Don't broadcast to 255.255.255.255. It was deprecated twenty years ago. Use the subnet broadcast address, or better still use multicast.
You can bind your socket to that port, if this port is occupied by a previous instance of your own program. You need to use "reuse" parameter in all instances of your program. Call .setReuseAddress(true); before binding.
Where can I find details on UDP in Java and how is a basic UDP communcation established?
This page provides detailed information on how to create a UPD server and client.
In essence, you create a server like this:
// Setup the socket
DatagramSocket socket = new DatagramSocket(12345);
// Receive a packet
byte[] buffer = new byte[512];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
// Do something with the data in the buffer
// and if necessary receive more packets
// Close the socket
socket.close();
On the client side, you can then send a packet like this:
// Create a socket
DatagramSocket socket = new DatagramSocket();
// Create a buffer and fill it with your data
byte[] buffer = new byte[512];
...
// Send the packet
InetAddress address = InetAddress.getByName("127.0.0.1");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, 12345);
socket.send(packet);
// Close the socket
socket.close();