
recently I have been looking into a latency-gap between the C and Haskell implementations of a TCP-echo One issue that has come up is that recvBufFrom calls getpeername() for each successful recvfrom(). This is unnecessary in the context of the code that I am working with as the result is discarded. My proposed solution to this is to implement recvBuf. I apologise in advance for my rudimentary Haskell skills. --- Network/Socket.hsc | 57 ++++++++++++++++++++++++++++++++++----------------- 1 files changed, 38 insertions(+), 19 deletions(-) diff --git a/Network/Socket.hsc b/Network/Socket.hsc index 21d83ac..13a94c2 100644 --- a/Network/Socket.hsc +++ b/Network/Socket.hsc @@ -81,6 +81,7 @@ module Network.Socket -- ** Sending and receiving -- $sendrecv , recv + , recvBuf , recvBufFrom , recvFrom , recvLen @@ -662,16 +663,10 @@ recvFrom sock nbytes = str <- peekCStringLen (ptr, len) return (str, len, sockaddr) --- | Receive data from the socket, writing it into buffer instead of --- creating a new string. The socket need not be in a connected --- state. Returns @(nbytes, address)@ where @nbytes@ is the number of --- bytes received and @address@ is a 'SockAddr' representing the --- address of the sending socket. --- -- NOTE: blocking on Windows unless you compile with -threaded (see -- GHC ticket #1129) -recvBufFrom :: Socket -> Ptr a -> Int -> IO (Int, SockAddr) -recvBufFrom sock@(MkSocket s family _stype _protocol _status) ptr nbytes +recvBufFrom' :: Socket -> Ptr a -> Int -> IO (Int, Ptr SockAddr) +recvBufFrom' sock@(MkSocket s family _stype _protocol _status) ptr nbytes | nbytes <= 0 = ioError (mkInvalidRecvArgError "Network.Socket.recvFrom") | otherwise = withNewSockAddr family $ \ptr_addr sz -> do @@ -687,17 +682,41 @@ recvBufFrom sock@(MkSocket s family _stype _protocol _status) ptr nbytes let len' = fromIntegral len if len' == 0 then ioError (mkEOFError "Network.Socket.recvFrom") - else do - flg <- sIsConnected sock - -- For at least one implementation (WinSock 2), recvfrom() ignores - -- filling in the sockaddr for connected TCP sockets. Cope with - -- this by using getPeerName instead. - sockaddr <- - if flg then - getPeerName sock - else - peekSockAddr ptr_addr - return (len', sockaddr) + else return (len', ptr_addr) + +-- | Receive data from the socket, writing it into buffer instead of +-- creating a new string. The socket need not be in a connected +-- state. Returns @(nbytes, address)@ where @nbytes@ is the number of +-- bytes received and @address@ is a 'SockAddr' representing the +-- address of the sending socket. +-- +-- NOTE: blocking on Windows unless you compile with -threaded (see +-- GHC ticket #1129) +recvBufFrom :: Socket -> Ptr a -> Int -> IO (Int, SockAddr) +recvBufFrom sock ptr nbytes = do + (len, ptr_addr) <- recvBufFrom' sock ptr nbytes + flg <- sIsConnected sock + -- For at least one implementation (WinSock 2), recvfrom() ignores + -- filling in the sockaddr for connected TCP sockets. Cope with + -- this by using getPeerName instead. + sockaddr <- + if flg then + getPeerName sock + else + peekSockAddr ptr_addr + return (len, sockaddr) + +-- | Receive data from the socket, writing it into buffer instead of +-- creating a new string. The socket need not be in a connected +-- state. Returns @(nbytes)@ where @nbytes@ is the number of +-- bytes received. +-- +-- NOTE: blocking on Windows unless you compile with -threaded (see +-- GHC ticket #1129) +recvBuf :: Socket -> Ptr a -> Int -> IO Int +recvBuf sock ptr nbytes = do + (len, ptr_addr) <- recvBufFrom' sock ptr nbytes + return len ----------------------------------------------------------------------------- -- send & recv -- 1.7.2.3