2012-09-25 62 views
9

我试图在使用Network.Socket模块构建的套接字上设置接收超时。这里有一个代码片段:在OSX上设置套接字选项

import Network.Socket 

host = "127.0.0.1" 
port = PortNumber 3000 

main = do 
    addrinfos <- getAddrInfo Nothing (Just host) (Just port) 
    let serveraddr = head addrinfos 
    sock <- socket (addrFamily serveraddr) Stream defaultProtocol 
    setSocketOption sock RecvTimeOut 120000000 
    connect sock (addrAddress serveraddr) 
    msg <- recv sock 1024 
    putStrLn msg 
    sClose sock 

setSocketOption行抛出异常:

*** Exception: setSocketOption: invalid argument (Invalid argument) 

setSocketOption只接受Int论据设置,但不是所有的插座选择想要的Int。具体RecvTimeOutSendTimeOut预计struct timeval。是否有另一种方法来设置哈斯克尔这些选项?

我在OSX运行GHC 7.4.2 10.8.1

编辑:

Network.Socket.Options似乎是最好的解决方案在这里,并得到它来编译OSX上横空出世只是要求小拉请求。从版本0.2.0.1开始,network-socket-options现在可以在OSX上编译。

编辑2: 没有运气与Network.Socket.OptionssetRecvTimeout函数似乎对OSX没有任何影响。我最终使用System.Timeout软件包中的timeout作为解决方法。

msg <- timeout 120000000 $ recv sock 1024 
+0

这是否帮助:HTTP:// WWW。 haskell.org/pipermail/haskell/2005-October/016586.html?或者这个:http://hackage.haskell.org/packages/archive/network-socket-options/0.2/doc/html/Network-Socket-Options.html? – paulsm4

+0

在Mac OS X和Linux上,GHC使用不受套接字超时影响的非阻塞套接字I/O。使用'System.Timeout'是超时I/O操作的正确方法。不幸的是,[网络I/O当前不能在Windows上中断](https://github.com/haskell/network/issues/75),所以你必须使用套接字超时作为解决方法。为了便于携带,请同时使用套接字超时*和*'System.Timeout'。 –

回答

2

我从这里了解Haskell和结构的定义:http://therning.org/magnus/archives/315 。从这里开始MSDN的timeval结构定义(及其对GNU大概在OSX相同结构):http://msdn.microsoft.com/en-us/library/windows/desktop/ms740560(v=vs.85).aspx

时间C-头:

... 
typedef struct timeval { 
    long tv_sec; 
    long tv_usec; 
} timeval; 
.... 

好像你需要定义某种结构的Haskell中的构造函数。或一个完整的结合一样,时间标头(来自http://hackage.haskell.org/packages/archive/bindings-common/0.1.4/doc/html/src/CTypes.html拍摄):

   module CTypes where 
import Foreign 
import Foreign.C 

-- time.h 

data Tm = Tm { 
    tm'sec, 
    tm'min, 
    tm'hour, 
    tm'mday, 
    tm'mon, 
    tm'year, 
    tm'wday, 
    tm'yday, 
    tm'isdst :: CInt 
    } 

instance Storable Tm where 
    sizeOf _ = fromIntegral size_of_tm 
    alignment = sizeOf 
    peek p = 
     with 0 $ \p1 -> with 0 $ \p2 -> with 0 $ \p3 -> 
     with 0 $ \p4 -> with 0 $ \p5 -> with 0 $ \p6 -> 
     with 0 $ \p7 -> with 0 $ \p8 -> with 0 $ \p9 -> 
     c2hs_tm p p1 p2 p3 p4 p5 p6 p7 p8 p9 >> 
     peek p1 >>= \v1 -> peek p2 >>= \v2 -> peek p3 >>= \v3 -> 
     peek p4 >>= \v4 -> peek p5 >>= \v5 -> peek p6 >>= \v6 -> 
     peek p7 >>= \v7 -> peek p8 >>= \v8 -> peek p9 >>= \v9 -> 
     return $ Tm v1 v2 v3 v4 v5 v6 v7 v8 v9 
    poke p (Tm v1 v2 v3 v4 v5 v6 v7 v8 v9) = 
     hs2c_tm p v1 v2 v3 v4 v5 v6 v7 v8 v9 

foreign import ccall size_of_tm :: CInt 

foreign import ccall hs2c_tm 
    :: Ptr Tm -> CInt -> CInt -> CInt -> CInt -> 
     CInt -> CInt -> CInt -> CInt -> CInt -> IO() 

foreign import ccall c2hs_tm 
    :: Ptr Tm -> Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> 
     Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> 
     Ptr CInt -> IO() 

-- sys/time.h 

data Timeval = Timeval {timeval'tv_sec, timeval'tv_usec :: CLong} 

instance Storable Timeval where 

    sizeOf _ = fromIntegral size_of_timeval 

    alignment = sizeOf 

    peek p = 
     with 0 $ \p1 -> 
     with 0 $ \p2 -> 

     c2hs_timeval p p1 p2 >> 

     peek p1 >>= \v1 -> 
     peek p2 >>= \v2 -> 

     return $ Timeval {timeval'tv_sec = v1, timeval'tv_usec = v2} 

    poke p v = hs2c_timeval p (timeval'tv_sec v) (timeval'tv_usec v) 

foreign import ccall "size_of_timeval" size_of_timeval 
    :: CInt 

foreign import ccall "hs2c_timeval" hs2c_timeval 
    :: Ptr Timeval -> CLong -> CLong -> IO() 

foreign import ccall "c2hs_timeval" c2hs_timeval 
    :: Ptr Timeval -> Ptr CLong -> Ptr CLong -> IO() 

一个精简必要的版本将是:

module CTypes where 
import Foreign 
import Foreign.C 

-- sys/time.h 

data Timeval = Timeval {timeval'tv_sec, timeval'tv_usec :: CLong} 

然后,您应该能够初始化的timeval结构由:

timeval <- Timeval { tv_sec=120 , tv_usec=0 } 

我希望有点帮助...