
On 2004-08-11 at 14:19BST Glynn Clements wrote:
Bayley, Alistair wrote:
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
This is rather more powerful than recvFrom in C, isn't it? Perhaps it's misnamed: C's recvFrom deals with finite messages, but with the above I can receive an infinite list, which is the source of the problem, even if rather cool.
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.
So the problem is the same as with hGetContents in general, compounded by the calling programme not having access to the socket, so it can't close it even if it knows it's finished with the data.
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.
Agreed, and recvFrom seems to need to be something else, though the problem could be ameliorated by making withSocketsDo close any leftover sockets. You'd then have to use it for both Linux and Windows.
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.
Given that, recvFrom could :: HostName -> Socket -> IO String. We'd have to call listenOn to get the socket, but that seems a small hardship compared to losing the use of the port. [1] What's the "Do" doing there anyway? You end up writing withSocketsDo$do, and we could do without the Do$do. -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk