I'm coding a networking application on Android.
I'm thinking of having a single UDP port and Datagram socket that receives all the datagrams that are sent to it and then have different processing queues for these messages.
I'm doubting if I should have a second or third UDP socket on standby. Some messages will be very short (100bytes or so), but others will have to transfer files.
My concern is, will the Android kernel drop the small messages if it's too busy handling the bigger ones?
Update "The latter function calls sock_queue_rcv_skb() (in sock.h), which queues the UDP packet on the socket's receive buffer. If no more space is left on the buffer, the packet is discarded. Filtering also is performed by this function, which calls sk_filter() just like TCP did. Finally, data_ready() is called, and UDP packet reception is completed."
To begin, try a value within the range 50,000 to 150,000 packets per second. Select an initial value based on capacity of the receiving CPUs to handle NIC interrupts. To reduce average latency, try raising the value. If the number of packets overwhelms any receiver, try a lower value.
Once the socket buffer is full, new packets arriving is dropped.
TCP vs UDP Once connected, a TCP socket can only send and receive to/from the remote machine. This means that you'll need one TCP socket for each client in your application. UDP is not connection-based, you can send and receive to/from anyone at any time with the same socket.
Let's get some basics down first:
Every socket has a receive and a send buffer. When network hardware signals the arrival of a new packet and the receive buffer is full, the packet is dropped. The buffer sizes are controlled via SO_RCVBUF
and SO_SNDBUF
socket options, see setsockopt(3)
. The OS sets some defaults (and there's the /etc/sysctl.conf
file). This is on a BSD system:
~$ sysctl -a|grep space net.inet.tcp.recvspace=16384 net.inet.tcp.sendspace=16384 net.inet.udp.recvspace=41600 net.inet.udp.sendspace=9216
The difference between TCP and UDP is that the former takes care of sequencing of data and retransmission of dropped packets, plus a flow control (slow reader slows down fast writer), while the latter doesn't.
So yes, using UDP to transfer files is not the best, but workable, option. One just have to reinvent a part of TCP and weigh that re-invention's overhead against the one of TCP. Then again, the general wisdom is that UDP is best suited for applications that can tolerate some packet reordering/loss (e.g. audio/video streams).
Then there's the mis-guided notion that every socket needs a separate thread for sending/receiving data, which is far from truth. Many excellent high-performance network applications have been written without threads, but using non-blocking sockets and some polling mechanism (see select(2)
, poll(2)
, epoll(7)
).
To the question itself:
Yes, the kernel might drop packets if the application is too busy to keep enough available space in sockets' receive buffers. But since each socket has its own, the separation of control and data streams would help. Personally though I would go for a simple TCP server setup - listen on a port, accept a connection per client, implement a meaningful protocol on top of a TCP stream. I agree that playing with UDP and low-level protocol state machines is a lot of fun, but it has been done already, and decades of research went into tuning TCP performance. What matters at the end of the day is reliability (first) and performance (second) of your application.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With