Network.Socket Woes

Hi all, I'm trying to do some standard socket stuff using the Network.Socket library. This example is a UDP server: import Network.Socket proto_udp :: ProtocolNumber proto_udp = 17 port = 10162 main = do s <- socket AF_INET Datagram 17 bindSocket s (SockAddrInet (PortNum port) iNADDR_ANY) putStrLn $ "Listening on port " ++ (show port) ++ "... " (msg, n, addr) <- recvFrom s 1024 putStrLn $ "Received " ++ (show n) ++ " bytes from " ++ (show addr) ++ ": " putStrLn (show msg) Using the equivalent C program (socket, bind, recvfrom) I'm able to successfully receive a 64 byte message from my test program. The Haskell version, however, does not return from recvFrom. I've also tried wrapping this in a withSocketsDo, with no effect. How can I proceed to debug/troubleshoot this program? Thanks, - Scott Bell

On Fri, Mar 7, 2008 at 8:10 AM, Scott Bell
my test program. The Haskell version, however, does not return from recvFrom. I've also tried wrapping this in a withSocketsDo, with no effect.
So this is a long standing, ah, issue with the Network modules. Try sending a UDP packet to port 45607 and you'll find that the Haskell code gets it. hex(45607) = 0xb227 0x27b2 = 10162 In short, PortNum doesn't do the endian conversion for you. And I don't know a good way to figure out the endianness of the underlying system from Haskell I'm afraid. I usually end up FFIing out to htons or just assuming that the system is little-endian. We should really fix this unless there's some trick that I've been missing all this time. AGL -- Adam Langley agl@imperialviolet.org http://www.imperialviolet.org

Adam,
This does the trick, thanks! I certainly would not have been
able to track down such an insidious `issue' without much
agony and despair.
- Scott
On Fri, Mar 7, 2008 at 10:48 AM, Adam Langley
On Fri, Mar 7, 2008 at 8:10 AM, Scott Bell
wrote: my test program. The Haskell version, however, does not return from recvFrom. I've also tried wrapping this in a withSocketsDo, with no effect.
So this is a long standing, ah, issue with the Network modules.
Try sending a UDP packet to port 45607 and you'll find that the Haskell code gets it.
hex(45607) = 0xb227 0x27b2 = 10162
In short, PortNum doesn't do the endian conversion for you. And I don't know a good way to figure out the endianness of the underlying system from Haskell I'm afraid. I usually end up FFIing out to htons or just assuming that the system is little-endian.
We should really fix this unless there's some trick that I've been missing all this time.
AGL
-- Adam Langley agl@imperialviolet.org http://www.imperialviolet.org

On Fri, Mar 07, 2008 at 10:56:32AM -0700, Scott Bell wrote:
Adam,
This does the trick, thanks! I certainly would not have been able to track down such an insidious `issue' without much agony and despair.
(haskell-cafe, my apologies for a message that's only tangentially on-topic. The content might be helpful, especially if you're writing socket apps.) Assuming you're on Linux, there are a few handy tools for this job: * 'netstat -nlp' (show listeners, with process name, numeric) * lsof -p $pid (list open file descriptors for PID) * strace -p $pid (trace system calls in running process) * strace /path/to/executable (trace system calls to stderr) * ls -l /proc/$pid/fd (peek at kernel's view of PID's fd table) There's also dtrace on Solaris and OS X, but I don't use those OSes, so I'm not too familiar with it. In Windows, there seems to be an embarassment of riches when it comes to profiling tools. Hope this helps, -- /jbm, but you can call me Josh. Really, you can!

Hello Adam,
Maybe you could use the binary package [1] to always encode the portNumber,
etc. in network byte order? Such as available put/get functions:
putWord16be :: Word16 -> Put
Hope this helps...
__
Donnie
1. http://hackage.haskell.org/cgi-bin/hackage-scripts/package/binary-0.4.1
On 3/7/08, Adam Langley
On Fri, Mar 7, 2008 at 8:10 AM, Scott Bell
wrote: my test program. The Haskell version, however, does not return from recvFrom. I've also tried wrapping this in a withSocketsDo, with no effect.
So this is a long standing, ah, issue with the Network modules.
Try sending a UDP packet to port 45607 and you'll find that the Haskell code gets it.
hex(45607) = 0xb227 0x27b2 = 10162
In short, PortNum doesn't do the endian conversion for you. And I don't know a good way to figure out the endianness of the underlying system from Haskell I'm afraid. I usually end up FFIing out to htons or just assuming that the system is little-endian.
We should really fix this unless there's some trick that I've been missing all this time.
AGL
-- Adam Langley agl@imperialviolet.org http://www.imperialviolet.org
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

"Adam Langley"
On Fri, Mar 7, 2008 at 8:10 AM, Scott Bell
wrote: my test program. The Haskell version, however, does not return from recvFrom. I've also tried wrapping this in a withSocketsDo, with no effect.
So this is a long standing, ah, issue with the Network modules.
Try sending a UDP packet to port 45607 and you'll find that the Haskell code gets it.
hex(45607) = 0xb227 0x27b2 = 10162
In short, PortNum doesn't do the endian conversion for you. And I don't know a good way to figure out the endianness of the underlying system from Haskell I'm afraid. I usually end up FFIing out to htons or just assuming that the system is little-endian.
The PortNumber type is an instance of Num, so it works if you do not use the PortNum constructor. Prelude Network.Socket> case 10162 :: PortNumber of PortNum p -> p 45607 Benedikt

On Fri, Mar 7, 2008 at 11:04 AM, Benedikt Schmidt
The PortNumber type is an instance of Num, so it works if you do not use the PortNum constructor.
Prelude Network.Socket> case 10162 :: PortNumber of PortNum p -> p 45607
And there was the trick that I've been missing all this time ;) I'll probably submit a documentation patch for this since I'm a Bear of Little Brain and this wasn't obvious to me. -- Adam Langley agl@imperialviolet.org http://www.imperialviolet.org

On Mar 7, 2008, at 11:46 AM, Adam Langley wrote:
And there was the trick that I've been missing all this time ;) I'll probably submit a documentation patch for this since I'm a Bear of Little Brain and this wasn't obvious to me.
That would be great - I have been doing the same thing, and was just a minute short of sending in the FORTRAN Programmer's solution. It would have really made your eyes burn. Donn Cave, donn@avvanta.com

On Fri, Mar 7, 2008 at 4:04 PM, Benedikt Schmidt
The PortNumber type is an instance of Num, so it works if you do not use the PortNum constructor.
Prelude Network.Socket> case 10162 :: PortNumber of PortNum p -> p 45607
Considering that PortNumber implements toEnum/fromEnum, why is PortNum exported anyway? -- Felipe.

Hello Adam,
After taking a closer look, the network module does do the ntohs() FFI call:
http://haskell.org/ghc/docs/latest/html/libraries/network/src/Network-Socket...
Thus, I think the issue is probably that Scott's UDP Client does not do the
htons() for the port number, or if the UDP Client is in Haskell, then it is
not using the Portnumber constructor.
__
Donnie
On 3/7/08, Adam Langley
On Fri, Mar 7, 2008 at 8:10 AM, Scott Bell
wrote: my test program. The Haskell version, however, does not return from recvFrom. I've also tried wrapping this in a withSocketsDo, with no effect.
So this is a long standing, ah, issue with the Network modules.
Try sending a UDP packet to port 45607 and you'll find that the Haskell code gets it.
hex(45607) = 0xb227 0x27b2 = 10162
In short, PortNum doesn't do the endian conversion for you. And I don't know a good way to figure out the endianness of the underlying system from Haskell I'm afraid. I usually end up FFIing out to htons or just assuming that the system is little-endian.
We should really fix this unless there's some trick that I've been missing all this time.
AGL
-- Adam Langley agl@imperialviolet.org http://www.imperialviolet.org
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (7)
-
Adam Langley
-
Benedikt Schmidt
-
Donn Cave
-
donnie Jones
-
Felipe Lessa
-
Josh Myer
-
Scott Bell