Message3070

Author rluse
Recipients amak, fwierzbicki, rluse
Date 2008-03-08.02:41:35
SpamBayes Score 0.00027722414
Marked as misclassified No
Message-id <1204944096.12.0.73728560176.issue1005@psf.upfronthosting.co.za>
In-reply-to
Content
Hi Alan,

Well I've done some homework today too, and I have found some
interesting things.  First, the IETF standard for UDP, RFC 768 is still
in effect.  It is dated August 1980.  Yes, Jimmy Carter was the US
President and I was programming on a Control Data main frame with FORTRAN!

Anyway, it is literally less than 3 pages long and you can read it in
less than 5 minutes.  The lines that mainly concern us are these:


User Interface
--------------

A user interface should allow

  the creation of new receive ports,

  receive  operations  on the receive  ports that return the data octets
  and an indication of source port and source address,

  and an operation  that allows  a datagram  to be sent,  specifying the
  data, source and destination ports and addresses to be sent.
-----

That's it.  User interface in this case means the application above UDP.

I also have finally bought and begun to read:

UNIX Network Programming Volume 1, Third Edition: The Sockets Networking API
By 	W. Richard Stevens; Bill Fenner; Andrew M. Rudoff

It is a bit slow going as you may expect, but I can already recommend it
to you.  It talks about the history and the common problems that have
developed.

It is interesting that he calls what you just started calling assigned
ports, ephemeral ports.  I like your name better. He also talks about
the history of why UDP does not notify the application when it receives
the ICMP message saying that there is no server on the port.  It also
talks about host addresses.  That there are situations where the local
address can change with with every send to the same server.  That looks
like it may explain some of the issues you were finding.     

For our case, you already fixed this situation:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto('testdata', ('192.168.1.103', 375))

buf, addr = s.recvfrom(2048)

If the server is up and it responds with a packet back, then this script
should read the packet and then the script should terminate.  Otherwise,
it should hang forever.  But, one thing that I wasn't thinking about was
this case:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto('testdata', ('192.168.1.103', 375))
s.sendto('testdata', ('192.168.1.104', 375))  # <- different host
s.sendto('testdata', ('192.168.1.104', 3750))  # <- different port

buf, addr = s.recvfrom(2048)

Multiple sends to multiple server through the UDP port. 
This should respond just like the previous one.  If it gets one packet
from any of these servers, it will read it and terminate, otherwise it
will hang forever.  Interestingly, your code handles this, but CPython
does not!  It is clearly a bug in CPython.  I haven't tried Java yet and
I am also setting up to try the equivalent C programs.

For the other case, when there is a recv with no send, I am coming
closer and closer to your opinion, that an error should be generated
rather than allowing the read.  I guess my main concern was that
existing CPython code that was running may break.  But, maybe that is a
good thing.  What I am going to do is run the equivalent in c of the
following two examples and see how c handles it.

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

buf, addr = s.recvfrom(2048)


and

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimout(2.0)
buf, addr = s.recvfrom(2048)

I will let you know the results.
History
Date User Action Args
2008-03-08 02:41:36rlusesetspambayes_score: 0.000277224 -> 0.00027722414
recipients: + rluse, fwierzbicki, amak
2008-03-08 02:41:36rlusesetspambayes_score: 0.000277224 -> 0.000277224
messageid: <1204944096.12.0.73728560176.issue1005@psf.upfronthosting.co.za>
2008-03-08 02:41:36rluselinkissue1005 messages
2008-03-08 02:41:35rlusecreate