2012-09-25 91 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 } 

我希望有點幫助...