
Bayley, Alistair wrote:
However, even if sClose was exported, that wouldn't be of any help in Jon's case, as neither of the sockets which recvFrom creates are visible outside of recvFrom.
Ahh, OK. I haven't used recvFrom/sendTo yet... (trying it now) ... When I try Jon's example with 6.2.1 (Win XP) I don't get the same error; it works twice and then hangs (my networking code would hang if I tried to re-use a socket that hadn't been properly closed).
Odd.
Is recvFrom meant to be a one-shot function i.e. the socket is only closed when the process exits?
The implementation is:
recvFrom host port = do ip <- getHostByName host let ipHs = hostAddresses ip s <- listenOn port let waiting = do ~(s', SockAddrInet _ haddr) <- Socket.accept s he <- getHostByAddr AF_INET haddr if not (any (`elem` ipHs) (hostAddresses he)) then do sClose s' waiting else do h <- socketToHandle s' ReadMode msg <- hGetContents h return msg
message <- waiting return message
Note that the listening socket s is passed to accept then forgotten about. If it was accessible, it would be possible to either accept further connections on it, or to close it. As it stands, it will remain open and unused for the duration of the calling process. A subsequent call to recvFrom would call listenOn again, attempting to create another listening socket on the same address and port. Obviously, that should fail so long as the original socket still exists (the kernel doesn't know that the original socket can't ever be used again).
Jon's second example uses listenOn/accept and handles, which is also what I used:
do sock <- listenOn$PortNumber 7607; (hdl,host,port)<- accept sock; s<-IO.hGetContents hdl; putStr$s; IO.hClose hdl; Network.Socket.sClose sock
Network.Socket.sClose is obviously useful here, so don't you think it would be a good idea to put it in Network? I don't see why including sClose would imply that you should start exposing other low-level stuff. AFAICT, it is the one little thing that's missing from Network that makes writing simple networking code possible.
There's a lack of symmetry (closure?): you can create a socket with Network.listenOn, but there is no corresponding close function in Network.
Right. If listenOn and accept are in Network, sClose should be in
there too. That would at least provide an API which is usable for the
simplest programs.
OTOH, the core problem with Network.recvFrom is essentially that it
appears to be a misguided attempt to provide a symmetric counterpart
to Network.sendTo. While the low-level sendTo/recvFrom functions may
be roughly symmetric, at a higher level, the client and server ends of
a connection aren't at all symmetric.
--
Glynn Clements