OnMessage() functionality for UDP - java

I was wondering if there is a type of OnMessage() type functionality for UDP messages using DatagramPacket? I want to be able to ensure that I get all messages when they come across so I don't waste resources randomly grabbing on a timer.
The OnMessage I am referring to the one done in WebSocketClient. Or some functionality similar to "Available" in .net.
While (rxUdpClient.Available > 0)
I am monitoring several ports so a thread is called which will do a run() for each port. Problem is I seem to have messages coming in at a massive rate 40+/sec.
This is what I currently have:
public void run()
{
DatagramSocket sock = null;
sock = new DatagramSocket(port);
byte[] buffer = new byte[DataAdapterFB1.HEADER_SIZE + DataAdapterFB1.MAX_DATA_BYTES];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
while (true){
sock.receive(incoming);
byte[] data = incoming.getData();
String s = new String(data, 0, incoming.getLength());
//This is the processing code, but it isn't its own thread...
ScadaMsg newMessage = new ScadaMsg(data);
}
}

DatagramPacket receive() operation is blocking, so what you will normally do is just launch a separate thread, which will listen for the incoming datagrams in a loop and dispatch them for further processing, like that:
void run() {
socket = new DatagramSocket(4445);
while(true) {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet); //JVM will wait here, until there is an incoming packet
onMessage(packet.getData())
}
}
public abstract void onMessage(final byte[] pkt);

Related

How to Continuously receive DatagramPackets in Java

I have written a client and server that are currently in an endless loop, that allow one message at a time to be sent and received. I need it to be able to continuously send/receive messages rather than be limited to one at a time.
Any idea on how I may go about this?
I am new to threads and not entirely sure how they work but i was thinking maybe a thread?
Client:
import java.io.*;
import java.net.*;
public class ClientChat {
DatagramSocket Socket;
public ClientChat(){
}
public void createAndListenSocket() throws SocketException, IOException{
while(true){
Socket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getLocalHost();
System.out.println("Type your message:");
BufferedReader message = new BufferedReader(new InputStreamReader(System.in));
byte[] incomingData = new byte[256];
String sentence = message.readLine();//"Testing from client";
byte[] data = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(data, data.length, IPAddress, 9876);
Socket.send(sendPacket);
System.out.println("Client: " + sentence);
DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length);
Socket.receive(incomingPacket);
String reply = new String(incomingPacket.getData());
System.out.println("Server: " + reply);
//Socket.close();
}
}
public static void main(String[] args) throws IOException{
ClientChat client = new ClientChat();
client.createAndListenSocket();
}
}
Server:
import java.io.*;
import java.net.*;
public class ServerClient {
public void run() throws Exception{
DatagramSocket Server = new DatagramSocket(9876);
while(true){
byte[] buf = new byte[1024];
DatagramPacket incomingPacket = new DatagramPacket(buf, buf.length);
Server.receive(incomingPacket);
String message = new String(incomingPacket.getData());
System.out.println("Client: " + message);
System.out.print("Server: ");
BufferedReader response = new BufferedReader(new InputStreamReader(System.in));
String reply = response.readLine();
InetAddress IPAddress = incomingPacket.getAddress();
int port = incomingPacket.getPort();
byte[] data = reply.getBytes();
DatagramPacket replyPacket = new DatagramPacket(data, data.length, IPAddress, port);
Server.send(replyPacket);
}
}
public static void main(String[] args) throws Exception {
ServerClient Server = new ServerClient();
Server.run();
}
}
You are correct. You should use two threads - one for sending and one for receiving. You will also need two buffers to store the data while it's waiting to be send or processed after receiving. Most likely, you'll want FIFO buffers (a simple two-sided synchronized queue). Then, your main thread can only deal with reading/writing data to the queue, and the sending/receiving threads will take care of the rest in the background.
The sending thread should try to read from sending queue in a loop. The read operation on queue should block (pause the thread) until data is available.
The receiving thread should run in a loop to read a datagram from network and store it into a "received" queue. Reading datagram from network will block, while storing into a queue will return immediately unless the queue is full.
When the program is finished, you have to somehow "break" the threads from their loop. For example, you can set "shouldExit" boolean to true in your main thread, and check it in your send/receive threads. If you don't care, you can also set threads to daemon mode or just call System.exit().
Size your queues appropriately. If too small, messages will get lost and/or threads will be blocked a lot of time. If too large, you will waste memory. For example, estimate (or observe) the average and maximum number of messages in a queue, and add a safety margin.

UDP Client in Java (Android) for getting Data from X-Plane 12

I try to read the UDP Stream from X-Plane 12 in Java.
This is what I try:
public class EchoClient {
#Test
public void echo() throws IOException {
DatagramSocket socket;
InetAddress address;
byte[] buf;
socket = new DatagramSocket();
address = InetAddress.getByName("localhost");
String msg = "TEST";
buf = msg.getBytes();
DatagramPacket packet
= new DatagramPacket(buf, buf.length, address, 49000);
socket.send(packet);
packet = new DatagramPacket(buf, buf.length);
System.out.println("hi there");
while(true) {
socket.receive(packet); // it "stops" here... without an error
String received = new String(
packet.getData(), 0, packet.getLength());
System.out.println(received);
}
}}
X-Plane is running and the UDP option is activated - but my program does print nothing on the console.. and it is runnig forever (while true)
Receive is blocked and waiting to a receive a packet. The packet you sent earlier is dropped on the floor because no one is listening.

How to interrupt a blocking call to UDP socket's receive() [duplicate]

This question already has answers here:
How to terminate a thread blocking on socket IO operation instantly?
(2 answers)
Closed 6 years ago.
I have a UDP server listening packets from a client.
socket = new DatagramSocket(port);
while (isListen) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, 0, data.length);
socket.receive(packet);
}
The receive() method will wait forever before a packet received. Is it possible to stop waiting for receiving? I can set a boolean isListen to stop the loop. On the other hand, if the socket is waiting then it will wait forever if no packet send from the client.
You need to set a socket timeout with the setSoTimeout() method and catch SocketTimeoutException thrown by the socket's receive() method when the timeout's been exceeded. After catching the exception you can keep using the socket for receiving packets. So utilizing the approach in a loop allows you to periodically (according to the timeout set) "interrupt" the receive() method call.
Note that timeout must be enabled prior to entering the blocking operation.
An example (w.r.t your code):
socket = new DatagramSocket(port);
socket.setSoTimeout(TIMEOUT_IN_MILLIS)
while (isListen) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, 0, data.length);
while (true) {
try {
socket.receive(packet);
break;
} catch (SocketTimeoutException e) {
if (!isListen) {} // implement your business logic here
}
}
// handle the packet received
}
You can close the socket from another thread. The thread blocked in receive() will then throw an IOException.
while (isListen) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, 0, data.length);
try {
socket.receive(packet);
} catch(IOException e) {
continue;
}
}
void stopListening() { // Call me from some other thread
isListen = false;
socket.close();
}

Udp Server Client java

I have written UDP server client program. The problem that i am facing is that when i am running server program, it is not waiting for client to connect. Whole code is executing after running till the end. And when i am running client side in between of execution of server side, client side is receiving data from its point of execution. Here is my server code-
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(4321);
byte[] sendData;
String sentence = null;
FileInputStream file = new FileInputStream(new File("E:\\Deepak.txt"));
InetAddress IPAddress=InetAddress.getByName("localhost");
BufferedReader in = new BufferedReader(new InputStreamReader(file));
do{
while((sentence = in.readLine()) != null)
{
Thread.sleep(3000);
System.out.println(sentence);
sendData = sentence.getBytes();
DatagramPacket sendPacket =new DatagramPacket(sendData, sendData.length,IPAddress,9876);
serverSocket.send(sendPacket);
}
}while(true);
}
Here is my client side code-
public static void main(String args[]) throws SocketException, UnknownHostException, IOException
{
DatagramSocket clientSocket = new DatagramSocket();
byte[] receiveData = new byte[1024];
String sentence ;
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
receivePacket.getLength();
System.out.println(receivePacket.getLength());
clientSocket.receive(receivePacket);
sentence = new String( receivePacket.getData());
}
}
UDP is connectionless, so there is no such thing as a connection in it.
You can only send a packet (in a fire and forget way, send in java will send the data to the port specified in the Datagram) or receive packet on the port (receive in java will block until there is a packet received).
So you would need to implement your own connection on top of UDP if you want to have a server that only sends data if client "connects" to it.
So summing up:
send won't wait for anything, it will just throw the datagram on the wire
receive will wait for a datagram to arrive
Having the above information you would need to write your own protocol to keep the connection.

transfer file by UDP but guaranti file not lost

I have a project require using UDP protocol to transfer file but still guaranty the feature of TCP protocol. That means we have the speed of UDP and the file not lost.
I've already have:
Server:
public class UDPServer {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
// TODO code application logic here
int port = 6788;
DatagramSocket sk = new DatagramSocket(port);
byte[] buf = new byte[1000];
while(true){
DatagramPacket request = new DatagramPacket(buf, buf.length);
sk.receive(request);
String msg = (new String(request.getData()));
DatagramPacket reply = new DatagramPacket(msg.getBytes(), msg.getBytes().length, request.getAddress(), request.getPort());
sk.send(reply);
}
}
}
Client:
public class UDPClient {
public static void main(String[] args) throws SocketException, UnknownHostException, IOException {
DatagramSocket sk = new DatagramSocket();
String msg = "message send";
InetAddress addr = InetAddress.getByName("localhost");
int port = 6788;
DatagramPacket request = new DatagramPacket(msg.getBytes(), msg.getBytes().length, addr, port);
sk.send(request);
byte[] buf = new byte[1000];
DatagramPacket reply = new DatagramPacket(buf, buf.length);
sk.receive(reply);
System.out.println("packet da nhan duoi client" + new String(reply.getData()));
sk.close();
}
}
and can you help me any suggest to guaranty file not lost ?. tks
You have quite big task, if you really want to implement fast and reliable file transfer with UDP.
With very small files (that fits in a single IP packet), it could be easy to avoid some overhead of TCP (like TCP connection opening and closing handshakes).
But If you are going to transfer bigger files, then you must implement many difficult features, like: flow control, selective acknowledges, re-transmissions and so on.
So I suggest to use TCP, instead of implementing own similar protocol.
You just CAN'T. It's not designed to be reliable.
If you manage to do it... it just means that you've implemented TCP yourself!, it will be much slower though.

Categories

Resources