Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How many requests can a java UDP socket handle?

I need to build a UDP server which can handle ~10_000 requests/sec. Started with below code, to test whether a java socket can handle those number of requests.

I am bombarding the server for a minute with ~9000 requests,

Total number of requests sent from the client : 596951

and in the tcp dump I see

90640 packets captured
175182 packets received by filter
84542 packets dropped by kernel

UDP Server code :

try (DatagramSocket socket = new DatagramSocket(port)) {
            System.out.println("Udp Server started at port :" + port);


            while (true) {
                byte[] buffer = new byte[1024];
                DatagramPacket incomingDatagramPacket = new DatagramPacket(buffer, buffer.length);
                try {
                    socket.receive(incomingDatagramPacket);
                    LinkedTransferQueue.add(incomingDatagramPacket);
                } catch (IOException e) {
                    e.printStackTrace();
                    continue;

                }


            }

        } catch (SocketException e) {
            e.printStackTrace();
        }

What is the the probable cause kernel dropping the packets in program this simple ?

How to reduce it ? Any other implementation ?

From this link, reading from the comments,lose of packets for UDP protocol can always happen even between network to java socket.recieve method.

Note: Have to figure out regarding anomalies in the tcpdump packets captured, but there is quite number of packets dropped.

The anomalies in the tcpdump is the lack of buffer space, In order to know the number of packets received , I am using the iptraf-ng which gives the number of packets received per port :)

like image 697
forum.test17 Avatar asked Sep 03 '17 11:09

forum.test17


1 Answers

Mutli-threading

Your code sample does nothing after the a packet is received. If that is the case, multi-threading cant help you.

However if that's just for testing and your actual application needs to do something with the received packet, you need to push the packet to another Thread (or a pool of them) and go immediately back to listening for the next packet.

Basically you need to minimize the time between two calls of the socket.receive().

Note: this is not the only mutli-threading model available for this case.

Buffer size

Increase the buffer size with socket.setReceiveBufferSize which maps to the SO_RCVBUF:

Increasing SO_RCVBUF may allow the network implementation to buffer multiple packets when packets arrive faster than are being received using receive(DatagramPacket).

However, this is just a hint:

The SO_RCVBUF option is used by the the network implementation as a hint to size the underlying network I/O buffers.

You could also, if your setup allows it, go directly to the OS and change the size of the buffer.

Irrelevant

Note: Read this only if you are not sure that the packet size is less than 1024 bytes.

Your packet buffer size seems low for generic packets, which can lead to bugs because: If a packet is larger than your buffer there will be no error, it will just ignore the overflowing bytes.

EDIT:

Other Multi-threading model

Note: This is an idea, I don't know if it actually works.

3 Threads:

  • Thread A: handling packets
  • Thread B1: receive packets
  • Thread B2: receive packets

Init:

  • Atomic counter set to 0
  • B1 is receiving, B2 is waiting.

While loop of the B1:

  • while counter > 0 wait
  • counter += 1
  • received the packet
  • counter -= 1
  • wake up the B2
  • push the packet to A's queue

Same for B2.

This the threads diagram (line where the packet has been received):

B1 [--------|---]    [--------|---]
B2          [--------|---]    [--------|---]
like image 170
MaanooAk Avatar answered Oct 27 '22 00:10

MaanooAk