I am trying to get UDP packets ,sent by device via WiFi, on my pc.
The device (kind of card) send every 2 seconds new packet.
The problem is that i do not get the packets on java client i have on my pc.
I see the packets on Wireshark.
Here is my UDP client (java):
public static void main(String args[]) {
try {
int port = 80;
// Create a socket to listen on the port.
DatagramSocket dsocket = new DatagramSocket(port);
dsocket.setSoTimeout(10000);
byte[] buffer = new byte[2048];
// Create a packet to receive data into the buffer
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// Now loop forever, waiting to receive packets and printing them.
while (true) {
// Wait to receive a datagram
try
{
dsocket.receive(packet);
}
catch (SocketTimeoutException e) {
continue;
}
// Convert the contents to a string, and display them
String msg = new String(buffer, 0, packet.getLength());
System.out.println(packet.getAddress().getHostName() + ": "+ msg);
// Reset the length of the packet before reusing it.
packet.setLength(buffer.length);
}
} catch (Exception e) {
System.err.println(e);
}
}
Related
Say I start a simple UDP server: nc -u localhost 10000
And a simple UDP client: nc -ul 10000
Then is it possible, in Java, to receive the messages sent by the server without getting an "Address already in use" exception because there's already a client?
EDIT: here's the code I'm using:
DatagramSocket socket = new DatagramSocket(port);
new Thread(() -> {
try {
while(true) {
byte[] receiveData = new byte[256];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket.receive(receivePacket);
String message = new String( receivePacket.getData(), 0, receivePacket.getLength()).trim();
}
}
catch (SocketException ignore) {}
catch (IOException e) { e.printStackTrace(); }
}).start();
This leads to a java.net.BindException: Address already in use (bind failed).
Using this:
DatagramSocket socket = new DatagramSocket(null);
socket.setOption(SO_REUSEPORT, true);
socket.setOption(SO_REUSEADDR, true);
new Thread(() -> {
try {
while(true) {
byte[] receiveData = new byte[256];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket.receive(receivePacket);
String message = new String( receivePacket.getData(), 0, receivePacket.getLength()).trim();
}
}
catch (SocketException ignore) {}
catch (IOException e) { e.printStackTrace(); }
}).start();
Produces no exception but I won't receive the messages sent by the server.
EDIT 2: in the real situation, the server is broadcasting messages.
This should be possible by utilizing StandardSocketOptions.SO_REUSEPORT:
For datagram-oriented sockets the socket option usually allows multiple UDP sockets to be bound to the same address and port.
The Linux Kernel supports this since 3.9.
On Windows, you might need to utilize SO_REUSEADDR, but I'm not exactly sure.
Using SO_REUSEADDR
The SO_REUSEADDR socket option allows a socket to forcibly bind to a port in use by another socket.
I've looking into multiple ways to do this and nothing has helped/worked new to Java UDP packets.
My code for Android is started via a service and it runs on a new thread.
Code for waiting:
try {
int port = 58452;
// Create a socket to listen on the port.
DatagramSocket dsocket = new DatagramSocket(port);
// Create a buffer to read datagrams into. If a
// packet is larger than this buffer, the
// excess will simply be discarded!
byte[] buffer = new byte[2048];
// Create a packet to receive data into the buffer
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// Now loop forever, waiting to receive packets and printing them.
while (true) {
// Wait to receive a datagram
dsocket.receive(packet);
// Convert the contents to a string, and display them
String msg = new String(buffer, 0, packet.getLength());
System.out.println(packet.getAddress().getHostName() + ": "
+ msg);
// Reset the length of the packet before reusing it.
packet.setLength(buffer.length);
}
} catch (Exception e) {
System.err.println(e);
}
Code for sending:
try {
String host = "MY PHONES IP";
int port = 58452; //Random Port
byte[] message = "LAWL,LAWL,LAWL".getBytes();
// Get the internet address of the specified host
InetAddress address = InetAddress.getByName(host);
// Initialize a datagram packet with data and address
DatagramPacket packet = new DatagramPacket(message, message.length,
address, port);
// Create a datagram socket, send the packet through it, close it.
DatagramSocket dsocket = new DatagramSocket();
dsocket.send(packet);
dsocket.close();
System.out.println("Sent");
} catch (Exception e) {
System.err.println(e);
}
}
It sends fine but won't receive on Android. Please help!
Also my Logcat output: http://pastebin.com/Rfw5mSKV
Thanks
-Fusion
http://systembash.com/content/a-simple-java-udp-server-and-udp-client/
I used that to and it works! Thanks to /u/TarkLark or Reddit!
So I try to create a simple server client application.
I have the server, which multicast messages to the subscribed clients.
The clients can obviously subscribe or unsubscribe.
Here is the server side code for the socket
try // create DatagramSocket for sending and receiving packets
{
socket = new DatagramSocket( 6666 );
} // end try
catch ( SocketException socketException )
{
System.exit( 1 );
} // end catch
I have also created a thread which waits for incoming pockets
while(true)
{
try // receive packet, display contents, return copy to client
{
byte[] data = new byte[ 100 ]; // set up packet
DatagramPacket receivePacket =
new DatagramPacket( data, data.length );
socket.receive( receivePacket ); // wait to receive packet
String Message = receivePacket.getData().toString();
.........
Here is the client side
try {
socket = new DatagramSocket();
} catch (SocketException ex) {
displayArea.append( ex + "\n" );
}
Here I try to send the packet
byte[] data = message.getBytes(); // convert to bytes
try {
// create sendPacket
DatagramPacket sendPacket = new DatagramPacket( data,
data.length, InetAddress.getLocalHost(), 6666 );
} catch (UnknownHostException ex) {
displayArea.append( ex + "\n" );
}
Well, the problem is that I don't think the packet reaches the server, I know the thread is waiting for the packet, I can see in debug that it does reaches the socket.receive part, however, nothing happens.
I'm using the client and server on the same computer.
Any idea what am I doing wrong?
Thanks.
byte[] data = message.getBytes(); // convert to bytes
try {
DatagramPacket sendPacket =
new DatagramPacket( data, data.length, InetAddress.getLocalHost(), 6666 );
socket.send( sendPacket ); //<<<<<<<<<<<<<<<<<<< REQUIRED
}
catch( UnknownHostException ex ) {
displayArea.append( ex + "\n" );
}
I've read many posts on this site on how to receive UDP packets in Android. However, none of this is working for me!
Some basics:
I am testing on my HTC Incredible (Android 2.2) running on 3G (not wifi or anything else). No emulators are involved here.
My code is simple:
My server (running on my PC) is listening for UDP traffic on port 8752.
My Android application opens a DatagramSocket on a random port and sends a packet to my server with this port.
I then save this information (the InetAddress form the received packet and the port found within the packet).
I try to send an UDP packet from my server (again, on my PC) to my Android app (running on my phone) and it does NOT work.
//Server code to initialize the UDP socket (snippet)
public void init() {
datagram_server_socket = new DatagramSocket(port,local_addr);
datagram_server_socket.setSoTimeout(1000);
}
//Snippet of code on the ANDROID APP that sends a packet to the server
public void connect() {
Random r = new Random(System.currentTimeMillis());
int udp_port = 0;
while(true){
try {
udp_port = r.nextInt(1000)+8000;
udp_port = 8000;
comm_skt = new DatagramSocket(udp_port);
Log.i("ServerWrapper", "UDP Listening on port: " + udp_port);
break;
} catch(SocketException e) {
Log.e("ServerWrapper", "Could not bind to port " + udp_port);
}
}
byte[] sdata = new byte[4+tid.length];
i = 0;
sdata[i++] = (byte)(0XFF&(udp_port>>24));
sdata[i++] = (byte)(0XFF&(udp_port>>16));
sdata[i++] = (byte)(0XFF&(udp_port>>8));
sdata[i++] = (byte)(0XFF&(udp_port));
for(byte b: tid){
sdata[i++] = b;
}
DatagramPacket pkt = new DatagramPacket(sdata, sdata.length,
InetAddress.getByName(hostname), port);
comm_skt.send(pkt);
}
//Server's UDP socket listening code
public void serverUDPListener() {
try {
datagram_server_socket.receive(rpkt);
int port = 0;
byte[] rdata = rpkt.getData();
port += rdata[0]<<24;
port += rdata[1]<<16;
port += rdata[2]<<8;
port += (0XFF)&rdata[3];
byte[] tid = new byte[rdata.length];
for(int i = 4; i < rdata.length && rdata[i] > 0; i++) {
tid[i-4] = rdata[i];
}
String thread_id = new String(tid).trim();
for(int i = 0; i < threads.size(); i++) {
ClientThread t = threads.get(i);
if(t.getThreadId().compareTo(thread_id) == 0) {
t.setCommSocket(rpkt, port);
} else {
System.err.println("THREAD ID " + thread_id + " COULD NOT BE FOUND");
}
}
} catch (IOException e) {
if(!(e instanceof SocketException) && !(e instanceof SocketTimeoutException))
log.warning("Error while listening for an UDP Packet.");
}
}
//Corresponds to the setCommSocket call above to save the IP and Port of the incoming UDP packet on the server-end
public void setCommSocket(DatagramPacket pkt, int port) {
comm_ip = pkt.getAddress();
comm_port = pkt.getPort(); //Try the port from the packet?
}
//Sends an UDP packet from the SERVER to the ANDROID APP
public void sendIdle() {
if(comm_ip != null) {
System.err.println("Sent IDLE Packet (" + comm_ip.getHostAddress() + ":" + comm_port + ")");
DatagramPacket spkt = new DatagramPacket(new byte[]{1, ProtocolWrapper.IDLE}, 2, comm_ip, comm_port);
DatagramSocket skt;
try {
skt = new DatagramSocket();
skt.send(spkt);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Right now I've hard coded the port my application uses to 8000. However, what's odd is that EVERYTIME I test my program (and view the IP/Port that is saved on my server), the port the packet came from is always 33081. I have a a thread constantly listening for UDP traffic in my Android App but the code never executes passed the "receive(packet)" part:
public void AndroidUDPListener() {
while(true) {
synchronized(stop) {
if(stop) return;
}
byte[] recieve_data = new byte[64];
DatagramPacket rpkt = new DatagramPacket(recieve_data, recieve_data.length);
try {
if(comm_skt == null)
continue;
comm_skt.receive(rpkt);
byte[] data = rpkt.getData();
switch(data[1]) {
case IDLE:
if(ocl != null) ocl.onCompletion(null);
break;
case KEEP_ALIVE:
break;
}
} catch (Exception e) {
if(!(e instanceof SocketException) && !(e instanceof SocketTimeoutException))
Log.w("ServerWrapper", "Error while listening for an UDP Packet.");
}
}
}
Does anyone see an issue in my code? Or is there some permission/settings I need to set on my application first? I have internet communication enabled.
Example Output (using the port from the packet getPort()):
Android App - Now listening for UDP traffic on port 8000
Android App - Sending packet to server
Server - Received packet from XXXXXX:33081
Server - Sending IDLE packet to XXXXXX:33081
Example Output (using the port from the packet data):
Android App - Now listening for UDP traffic on port 8000
Android App - Sending packet to server
Server - Received packet from XXXXXX:8000
Server - Sending IDLE packet to XXXXXX:8000
The Android App never receives any UDP traffic from using either of the ports.
Sorry for not updating this sooner. The problem was fixed as follows:
I needed to store the DatagramSocket to each thread. The listening socket should also be the socket used to continue communication between the server and client. Here are the bits of updated code.
New socket registration code on thread:
public void setCommSocket(DatagramPacket pkt, int port, DatagramSocket skt)
{
comm_ip = pkt.getAddress();
comm_port = pkt.getPort();
synchronized(comm_pkt) {
comm_pkt = pkt;
}
comm_skt = skt;
}
New Server Listening Code:
public void UDPListen() {
while(true) {
synchronized(stop) {
if(stop)
break;
}
byte[] recieve_data = new byte[64];
DatagramPacket rpkt = new DatagramPacket(recieve_data, recieve_data.length);
try {
datagram_server_socket.receive(rpkt);
int port = 0;
byte[] rdata = rpkt.getData();
port += rdata[0]<<24;
port += rdata[1]<<16;
port += rdata[2]<<8;
port += (0XFF)&rdata[3];
byte[] tid = new byte[rdata.length];
for(int i = 4; i < rdata.length && rdata[i] > 0; i++)
{
tid[i-4] = rdata[i];
}
String thread_id = new String(tid).trim();
for(int i = 0; i < threads.size(); i++) {
ClientThread t = threads.get(i);
if(t.getThreadId().compareTo(thread_id) == 0)
{
t.setCommSocket(rpkt, port, datagram_server_socket);
} else {
System.err.println("THREAD ID " + thread_id + " COULD NOT BE FOUND");
}
}
} catch (IOException e) {
if(!(e instanceof SocketException) && !(e instanceof SocketTimeoutException))
log.warning("Error while listening for an UDP Packet.");
} finally {
for(int i = 0; i < threads.size(); i++) {
ClientThread t = threads.get(i);
t.sendKeepAlive();
}
}
}
}
There was some update to the structure of the server/threads that I will omitt. The important part here is that the socket in which the packet was recieved with was re-used to send data back to the client. Additionally, the actual packet was re-used to send data back:
public void sendIdle() {
if(comm_ip != null) {
synchronized(comm_pkt) {
try {
comm_pkt.setData(new byte[]{1, ProtocolWrapper.IDLE});
comm_skt.send(comm_pkt);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Here is the relevant parts of my wrapper class that shows what each thread was holding:
public class PeerWrapper {
private InetAddress ipaddress;
private Integer port;
private Socket client_socket;
private InetAddress comm_ip;
private DatagramSocket comm_skt;
private DatagramPacket comm_pkt;
private int comm_port;
private byte status;
I had a similar problem. On the Android was two sockets (sending/listening), and on a PC server was again two sockets (sending/listening). The phone would ping the PC's known listening socket with the address of the phone's unknown listening socket, so the PC could reply. Nothing I was doing appeared to be getting the address of the listening socket, as the socket would never receive anything.
This solved my problem: Android: java.net.DatagramSocket.bind: Invalid Argument Exception. Use a channel to create the socket, then binding on null. Now I can use the sending socket on the phone to send a packet containing the port of the listening socket (the IPs are the same) to the PC, obtained with .getLocalPort() The PC reads the byte[], gets the port, and sends packets back to the phones listening port.
android have inbound firewall
you have to use first udop hole punch same sock object with timer
I am trying to program a Java stop-and-wait UDP server and I have gotten this far with the server but I am not sure where to go next. I want the client to send a message to the server, set a timeout, wait for a response, if it doesn't get one, then resend the packet, if it does then increment the sequence no. until it get to ten and keep send and receiving messages with the server.
I have gotten this far, how do I fix this ? :
import java.io.*;
import java.net.*;
public class Client {
public static void main(String args[]) throws Exception {
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
InetAddress IPAddress = null;
try {
IPAddress = InetAddress.getByName("localhost");
} catch (UnknownHostException exception) {
System.err.println(exception);
}
//Create a datagram socket object
DatagramSocket clientSocket = new DatagramSocket();
while(true) {
String sequenceNo = "0";
sendData = sequenceNo.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 6789);
clientSocket.send(sendPacket);
clientSocket.setSoTimeout(1);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
if(clientSocket.receive(receivePacket)==null)
{
clientSocet.send(sendPacket);
}else { //message sent and acknowledgement received
sequenceNo++; //increment sequence no.
//Create a new datagram packet to get the response
String modifiedSentence = sequenceNo;
//Print the data on the screen
System.out.println("From : " + modifiedSentence);
//Close the socket
if(sequenceNo >= 10 ) {
clientSocket.close();
}
}}}}
The first problem I can see (apart from the mistyped variable names which will stop your code compiling) is your socket timeout: if the socket timeout expires, the receive function will throw a SocketTimeoutException which your code does not handle. receive does not return a value, so the result can't be compared with null. Instead, you need to do something like this:
try {
clientSocket.receive(receivePacket);
sequenceNo++;
... // rest of the success path
} catch (SocketTimeoutException ex) {
clientSocket.send(sendPacket);
}