appl'n
/ \
UDP UDP
/ \
server A server B
/ \
TCP TCP
/ \
client A client B
System: HP 720 running HP-UX
Details:
- The server-client connections are TCP.
- The server-appl'n connections are UDP.
- Client A sends a I/O stream (actually an mpeg file) via TCP to server A.
- Server A packetizes the I/O stream into 40-byte packets and forwards
them as UDP datagrams to the appl'n.
- The appl'n routes the 40-bytes packets as UDP datagrams to server B.
- Server B writes each 40-byte packet received to the TCP socket to
client B.
Problem:
The mpeg file transfer experiences high throughput for about 5 seconds
but then slows to a crawl, due to what I expect is buffer exhaustion.
If I don't throttle the rate at which server A injects datagrams to
the appl'n then much data is lost over UDP. The TCP writes will block
if there are no buffers but I don't think blocking occurs for UDP.
What I would like is for the UDP socket writes to block when there are
no buffers. I am assuming that these writes do not block but have yet
to verify this.
Questions:
1) Is my assumption that writes to UDP sockets are non-blocking correct?
(Well, if they do block then how does data get lost?). If they don't
block how can I make them block?
2) If they do block, should I just increase the amount of buffer space to
increase system throughput?
UDP is an unreliable datagram protocol. It specifically does not guarantee
delivery of the data. By using UDP, you are instructing the computer to
try to send the data and they forget it.
It appears that you want reliable data transfer, which is the province of TCP.
If all your "packets" are exactly 40 bytes, just send them as a stream and
separate them at the other end. If they are variable length, put a length
header on them.
The slow-down occurs because you have consumed all the networking resources
of your computers with a mass of tiny packets.
--------------------------------------------------------------------------------
Joseph A. Reuter, Wizard-in-Training,
speaking for myself from reu...@venice.sedd.trw.com
"Olorin I was in my youth in the West that is forgotten."--J. R. R. Tolkien
What's going on here is as follows. When you write to a UDP socket
the only thing the socket send buffer size is used for is to verify
that your datagram is smaller than this size. If that's OK then
the UDP data is encapsulated in a UDP datagram, then an IP datagram,
then a data-link frame, and then appended to the send queue of the
appropriate interface. Each interface has a queue limit, typically
50 on most BSD-derived systems. If that queue is full, your write
(or sendto) returns an error (ENOBUFS, I think). No, I don't think
you can increase the "50" without kernel sources on most systems.
When you get ENOBUFS all you can do is slow down (i.e., pause) and
try again.
Then, once the packets get onto the wire, you enter a whole new
set of problems with UDP (i.e., the problems of a connectionless,
unreliable protocol with no flow control).
Rich Stevens