non-blocking udp socket in java

Question:

There is a server on which a daemon must run (a background process, no matter what it is called) that constantly processes an array of information. Periodically, he should check whether any messages from network clients have arrived and, if they have arrived, write them to the database. Due to certain restrictions, clients send messages to the server exclusively using the udp protocol.
If I understood the reading literature on working with udp sockets correctly, then it will look something like this:

– somewhere first we initialize the socket on a specific port

try {
    socket = new DatagramSocket(port);
}
catch (SocketException e) {
    // Сообщение об ошибке, возможно остановка всего демона, если ничего не вышло
}

– then we do the main work of the daemon and at certain moments we try to get information from the socket:

byte[] bytes = new byte[1024];
DatagramPacket p = new DatagramPacket(bytes, bytes.length);
try {
    socket.receive(p);
}
catch(IOException e) {
}

As far as I understand, if no client has sent a data packet, then at this stage everything will stop and the process will wait for the data to arrive on the socket. Right?
And I need the work to continue regardless of whether the data is received or not. If received – well – recorded them in the database, if not, well, okay – there is still a lot of work.
In C ++, it is possible to switch the socket to non-blocking mode, it looks like this:

int nonBlocking = 1;
if ( fcntl( handle, F_SETFL, O_NONBLOCK, nonBlocking ) == -1 )
{
    printf( "failed to set non-blocking socket\n" );
}

for UNIX and MAC and

DWORD nonBlocking = 1;
if ( ioctlsocket( handle, FIONBIO, &nonBlocking ) != 0 )
{
    printf( "failed to set non-blocking socket\n" );
}

for WINDOWS
where handle is a handle to the socket.
In this mode, when reading from a socket, in the case when there is no data in it,

int received_bytes = recvfrom( handle, (char*)packet_data,
maximum_packet_size, 0, (sockaddr*)&from, &fromLength );

the program won't stop and received_bytes will just be zero.
Is there a way in Java to put a udp socket in non-blocking mode? Or is it necessary to poll the socket in a separate thread and implement some kind of eventing when receiving data? Non-blocking sockets, in my case, would be good because the socket should be polled at certain points in the processing of the main data and if some information is received, then it must be stored with binding to certain keys from the main data, the rest of the time received by udp -packages are not important, you can just drop them.
Having skimmed through the results of search queries, I did not find the functionality I needed in Java.


Why the stream is inconvenient for me, I'll try to explain: the whole thing is connected with a complex security alarm and video surveillance system. Roughly speaking: some pieces of iron (iron1) constantly write some data to the database. One of the processes on the server (process1) constantly monitors this database and, when certain new data is found in it, sends messages to other pieces of iron (iron2). Those, in turn, having received messages, carry out certain actions and checks (it takes some time) and, if any events occur, they send data to the server using the udp protocol. There was a task to receive these messages (it is not critical if some will be lost), to compare them with data from the database and, in case of some coincidences, to log them. The existing software cannot be changed – there is no source code.

So the problem is that iron2, sending messages, does not put any timestamps there. It can also send messages on its own, not initiated by requests from the process1. And it would be convenient for me to monitor the database in my process (simultaneously with another process, this has already been implemented and there are no difficulties with this) and try to read data from the socket only at certain moments when specific data appears there (in the database) (these events occur quite rarely, every two to three hours), and the rest of the time, just periodically flush the socket data (if the hardware sent something there), as unnecessary. Otherwise, I can get a bunch of data sent recently, which have nothing to do with the events I need, but you can find out only by differentiating it all by time, and there are no time stamps (I repeat) in the messages of iron2

If you implement this in a separate thread, then for me there are certain difficulties with creating events and calling them. And a non-blocking socket is ideal in this case. Moreover, there is definitely such functionality in C ++, it works and works perfectly. So the question arose: is it possible that Java has similar functionality? At the same time, since I have to do everything in this particular programming language, I will develop and learn something new for myself.

Answer:

In Java, all non-blocking IOs are contained in the java.nio.channels package. Non-blocking UDP is implemented by the DatagramChannel class:

You can use something like this:

DatagramChannel chan = DatagramChannel.open();
chan.configureBlocking( false );
chan.bind( new InetSocketAddress( 7777 ) );

ByteBuffer buffer = ByteBuffer.allocate( 4*1024 );

while (true) {
    buffer.clear();
    System.out.println("trying non-blocking receive...");
    SocketAddress from = chan.receive(buffer);
    System.out.println("non-blocking receive done.");

    if (from != null) {
        buffer.flip();
        System.out.printf("<<<--- got [%x] byte from %s%n", buffer.get(), from);
    }

    System.out.println( "sleeping..." );
    TimeUnit.SECONDS.sleep( 5 );
}
Scroll to Top