views:

315

answers:

5

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."

A: 

Transferring files via UDP, huh that sounds BAD. UDP does not assure packets reach their destination. For transferring files use TCP as if not you will end up with a corrupted file.

Keep 1 UDP for incoming connections, roll out a new thread/connection(UDP/TCP) for each new job. Keep a 2nd UDP for outgoing connections. So you got commands in UDP1, and you respond via UDP2 or for transfering files via TCP. This way you assure all incoming requests are handled properly if watching is in thread.

Pentium10
+1  A: 

UDP is a bad idea for transferring files, as you cannot guarantee the order in which packets will be received, or whether they will be received at all. If you are thinking to build a fault tolerant transport layer on top of this, you should just use TCP/IP instead, as that's exactly what it does.

UDP does not buffer or queue received packets. If a packet is received and you are waiting for data, you will receive it. If a packet is received while your program is busy doing some other processing, you won't get the packet at all. So if you receive two "simultaneous packets" (well, two very close together) there is a good chance you might miss one of them if you are doing any significant processing of each packet.

I don't see how having extra ports open will help you much. If you're busy processing a packet from port 1, then you'll miss any packets coming in on any other ports you're watching, unless each is running on a dedicated thread. You would be much better off copying the packet quickly into your own buffer and passing it on to another thread to process it, so your listener thread can get back to listening asap.

Jason Williams
I can't do TCP since I don't want to have a thread taking care of each file I'm sending (think many simultaneous transfers), I've implemented a simple logic that just asks for the missing pieces of the file until it's done and it's working solidly.I read that the kernel does have a UDP buffer, and once full it'll discard packets.So yes, the thread receiving the UDP packets will immediately store those packets in processing queues that'll be handled by just a handful of worker threads, that way the UDP socket will be available as much as possible and the kernel's UDP buffer won't be full.
Gubatron
You won't be able to detect when a packet has been lost on UDP. You want to reinvent the wheel, and you will fail
Pentium10
A: 

TCP's flow control will help you reduce dropped packets. Its fault tolerant and makes sure that packet will arrive in sequence.

Jack
+2  A: 

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.

Nikolai N Fetissov
most excellent answer Nikolai. I was actually thinking last night that the way to go will be TCP and NIO. My device just can't handle too many threads, and it will def. have a lot of incoming requests.
Gubatron
You know you can *accept* answers, right? :)
Nikolai N Fetissov
UDP is only useful if the data needs to be updated in real-time and can't suffer the expense of retransmissions. Examples of such a connection include streaming videos/music, real time gaming where latency really matters, or file transfers (FTP) where the data chunks are being verified by CRC checks on the receiving end anyway.
Evan Plaice
Hmm, DNS doesn't fit any of your criteria.
Nikolai N Fetissov
A: 

It can be done to beat TCP for stream transfer using UDP if you don't have NAT to think about.

However having to ask this question (hint: the answer is "it doesn't matter") probably indicates you should not be doing it.

Joshua