haskell http 服务器的 acceptFork

haskell acceptFork for http server

我必须在 haskell 中创建一个 http 服务器。为此,我必须定义一个 acceptFork 函数来处理传入的 TCP 连接,它具有以下类型:

acceptFork :: Socket -> (Handle -> IO ()) -> IO ()

其工作方式如下:

到目前为止我想到的是:

import qualified Network.Socket as NS

acceptFork :: Socket -> (Handle -> IO ()) -> IO ()
acceptFork lsock k = do
    (csock,_) <- NS.accept lsock
    hSetBuffering lsock NoBuffering
    hSetNewlineMode lsock (NewlineMode CRLF CRLF)
    forkIO (k csock) 

问题是它甚至无法编译。有人可以解释我做错了什么吗?谢谢!

这是我得到的错误:

bead2.hs:31:23:
Couldn't match expected type `(Handle -> BufferMode -> IO ())
                              -> Socket
                              -> BufferMode
                              -> (Handle -> NewlineMode -> IO ())
                              -> Socket
                              -> NewlineMode
                              -> IO (Handle, t0)'
            with actual type `IO (Socket, NS.SockAddr)'
The function `NS.accept' is applied to 7 arguments,
but its type `Socket -> IO (Socket, NS.SockAddr)' has only one
In a stmt of a 'do' block:
  conn@(csock, _) <- NS.accept
                       lsock
                       hSetBuffering
                       lsock
                       NoBuffering
                       hSetNewlineMode
                       lsock
                       (NewlineMode CRLF CRLF)
In the expression:
  do { conn@(csock, _) <- NS.accept
                            lsock
                            hSetBuffering
                            lsock
                            NoBuffering
                            hSetNewlineMode
                            lsock
                            (NewlineMode CRLF CRLF);
       forkIO (k csock) }

bead2.hs:34:5:
Couldn't match type `ThreadId' with `()'
Expected type: IO ()
  Actual type: IO ThreadId
In a stmt of a 'do' block: forkIO (k csock)
In the expression:
  do { conn@(csock, _) <- NS.accept
                            lsock
                            hSetBuffering
                            lsock
                            NoBuffering
                            hSetNewlineMode
                            lsock
                            (NewlineMode CRLF CRLF);
       forkIO (k csock) }

好的,我复制了你的内容并添加了缺失的部分(网络 > 2.6 和 < 2.7):

import qualified Network.Socket as NS
import System.IO (Handle, hSetBuffering, hSetNewlineMode, BufferMode(..), Newline(..), NewlineMode(..), IOMode(..))
import Control.Concurrent (forkIO, ThreadId)

acceptFork :: NS.Socket -> (Handle -> IO ()) -> IO ThreadId
acceptFork lsock k = do
    (csock,_) <- NS.accept lsock
    hsock <- NS.socketToHandle csock ReadWriteMode
    hSetBuffering hsock NoBuffering
    hSetNewlineMode hsock (NewlineMode CRLF CRLF)
    forkIO (k hsock)

基本上你有:

  • 大量缺失进口
  • 需要通过NS.socketToHandle
  • 从套接字中获取句柄
  • 注意 forkIO 的结果(新线程的 id)

这个编译在:

 base >=4.8 && <4.9, network >=2.6 && <2.7

免责声明

我没有没有 运行这个代码所以我不知道它是否有效 - 但它会编译(在我的系统上;))

没有ThreadId:

只需更改签名和最后一行:

acceptFork :: NS.Socket -> (Handle -> IO ()) -> IO ()
acceptFork lsock k = do
    -- ... same as above
    _ <- forkIO (k hsock)
    return ()

分叉并等待下一个连接:

只需递归调用acceptFork

acceptFork :: NS.Socket -> (Handle -> IO ()) -> IO ()
acceptFork lsock k = do
    (csock,_) <- NS.accept lsock
    hsock <- NS.socketToHandle csock ReadWriteMode
    hSetBuffering hsock NoBuffering
    hSetNewlineMode hsock (NewlineMode CRLF CRLF)
    _ <- forkIO (k hsock)
    acceptFork lsock k

或使用forever

...
import Control.Monad (forever)

acceptFork :: NS.Socket -> (Handle -> IO ()) -> IO ()
acceptFork lsock k = ...

acceptAll :: NS.Socket -> (Handle -> IO ()) -> IO ()
acceptAll sock = forever . acceptFork sock