UDP packets not received in emulator from localhost - java

My app is unable to receive the UDP packets when running in the emulator. UDP packets are sent by below java program on "localhost" over the port 49999.
DatagramSocket clientsocket;
DatagramPacket dp;
BufferedReader br;
InetAddress ia;
byte buf[] = new byte[1024];
int cport = 50000, sport = 49999;
clientsocket = new DatagramSocket(cport);
dp = new DatagramPacket(buf, buf.length);
br = new BufferedReader(new InputStreamReader(System.in));
ia = InetAddress.getLocalHost();
while(true)
{
Random rand = new Random();
String str1 = rand.nextInt(100) + "";
buf = str1.getBytes();
System.out.println("Sending " + str1);
clientsocket.send(new DatagramPacket(buf,str1.length(), ia, sport));
try{
Thread.sleep(100);
} catch(Exception e){}
}
Another java UDP server program running on the same localhost receives the packets fine. This means that the packets are sent to localhost:49999 correctly.
To forward the packets from localhost to the emulator, I did telnet redirect as below:
telnet localhost 49999
redir add udp:49999:49999
The UDP receiver in the app looks like this:
byte[] data = new byte[1400];
DatagramPacket packet = new DatagramPacket(data, 1400);
DatagramSocket socket = new DatagramSocket(49999);
socket.setSoTimeout(200);
try{
socket.receive(packet); ---->> This throws a SocketTimeoutException
} catch(SocketTimeoutException e){}
My understanding was that the telnet redirect should take care of forwarding the packets from my development machine's localhost:49999 to emulator's localhost:49999 so that the data is available on the DatagramSocket(49999). However it keeps throwing the SocketTimeoutException all the time.
It would be a great help to know what is the missing piece of the puzzle here.

After connecting to the localhost you may want to check that the port was actually asigned as intended with the command netstat -na in the cmd. It also might be worth a try to use the IP 127.0.0.1 instead.

Related

UDP allocating a new socket for each new connection

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

Java Sending a short String via Socket in a high frequency

I am trying to make an application to control DMX Channels. For this I have an ESP8266 which takes a String as an input like "2.255", where the first integer is the DMX Channel and the second integer the value.
For my PC I wrote a method that first builds the string and then sens it to the IP Address of the ESP8266 via a Socket.
for(DMXChannel c : list){
if(lastvalue.get(c.getChannelID() - 1) != c.getValue()){
try {
String msg = c.getChannelID() + "." + c.getValue();;
DatagramSocket clientSocket = new DatagramSocket();
InetAddress ipaddr = InetAddress.getByName(ip); //IP Address is "192.168.4.1"
byte[] sendData = new byte[1024];
sendData = msg.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ipaddr, 8888);
clientSocket.send(sendPacket);
clientSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
This works fine but I have a problem when I am trying to do a fade. The frequency of this piece of code seems to be too slow.
Does anyone have a "faster" solution?
Here are some things you could do to speed up the code:
Do not call getByName for an IP address. This involves DNS, but DNS is not needed for an IP address. Instead call getByAddress. If you do need to call getByName, call it only once and cache the answer.
Do not open, close, reopen, etc. the socket each time. Just keep it open.

Java Broadcasting: throw BindException

I want that my client application is able to connect to a Server application.
The problem is that my Client doesn't know the Server ip (in LAN).
So I tried to use java object MulticastSocket. Luckily Oracle have a page with an example of Broadcasting.
Here I have rearranged it for my use.
Server code:
long FIVE_SECONDS = 5000;
int port = 4445;
DatagramSocket socket = new DatagramSocket(port);
while (true) {
System.out.println("Server running...");
try {
// message for client
String dString = "Hello Client";
byte[] buf = dString.getBytes();
// send
InetAddress group = InetAddress.getByName("230.0.0.1");
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port);
socket.send(packet);
// sleep for a while
try {
Thread.sleep((long)(Math.random() * FIVE_SECONDS));
}
catch (InterruptedException e) {
System.err.println("Interrupted Exception");
}
} catch (IOException e) {
System.err.println("IOException");
}
}
Client code:
MulticastSocket socket = new MulticastSocket(4445);
InetAddress address = InetAddress.getByName("230.0.0.1");
socket.joinGroup(address);
// receive the message
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println("Received: " + received);
socket.leaveGroup(address);
socket.close();
When I run Srver: no problem, but when I try running client it throw java.net.BindException: Address already in use cause both client and server are listening/sending information on port 4445.
But isn't it right? To connect each other they must have the same port number, or they'll never 'meet'.
Can I solve this problem? How?
Are the port number correct?
Is this a right resolution to the problem about the unknown server ip?
Thanks!
As Warren mentioned in his answer, your client and server can't bind to the same port on the same machine. The Oracle example is not doing that.
The client should bind to port 4446 and the server should bind to port 4445. When the server create a DatagramPacket it should do so with the client's port which is 4446.
If you do this and the client still can't receive, you may need to set the outgoing interface for multicast on the server. You can do this with either the setInterface or setNetworkInterface methods.
For example, suppose your serverhas IP addresses 192.168.1.1 and 192.168.2.1. If you want your sender to send from 192.168.1.1, you would call:
multicastSocket.setInterface(InetAddress.getByName("192.168.1.1"));
You are getting this exception because you are trying to run your server application and your client application on the same machine. When you start your client, your server has already bound to port 4445, so it is already in use - and thus unavailable - when your client tries to bind to it.
Running your server and your client on different machines would get around that particular error. However, you could also get around it by choosing different ports for your server and your client.
For example if you ran your server on port 4445, and your client on port 4446, you could do the following. On the server, you would add a variable for the client port, and use the client port as the destination port when sending your DatagramPacket:
int clientPort = 4446;
...
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, clientPort);
instead of
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port);
On the client, you would simply bind to the client port instead of the server port:
MulticastSocket socket = new MulticastSocket(4446);
instead of
MulticastSocket socket = new MulticastSocket(4445);
Using different port numbers for the server and for the client would allow you to run both the server application and the client application on the same machine and get you past this particular issue.

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.

Cannot bind Address already in use

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.

Categories