haskell websocket示例

时间:2012-03-14 03:15:24

标签: haskell websocket

import Network
import System.IO
import Control.Concurrent
import Control.Monad(when)
import Char

serverHandshake :: String
serverHandshake = 
 "HTTP/1.1 101 Switching Protocols\r\n\
 \Upgrade: WebSocket\r\n\
 \Connection: Upgrade\r\n\
 \Sec-WebSocket-Accept: *******************\r\n\r\n"

acceptLoop socket = forever $ do
 (h,_,_) <- accept socket
 ------------------------
 hPutStr h serverHandshake
 hSetBuffering h NoBuffering
 forkIO (listenLoop h)  
 where
  forever a = do a; forever a

main = withSocketsDo $ do
 h <- listenOn (PortNumber 8000)
 acceptLoop h
 sClose h
 return ()

listenLoop :: Handle  -> IO ()
listenLoop h = do
 sendFrame h "aleloia"
 msg <- readFrame h
 putStrLn msg
 when (msg /= "quit") (listenLoop h)

readFrame :: Handle -> IO String
readFrame h = readUntil h ""
 where
  readUntil h str = do
   new <- hGetChar h
   if new == chr 0
    then readUntil h ""
    else if new == chr 255
     then return str
     else readUntil h (str ++ [new])

sendFrame :: Handle -> String -> IO ()
sendFrame h s = do
 hPutChar h (chr 0)
 hPutStr h s
 hPutChar h (chr 255)

1)当有“forkIO(listenLoop h)”时,为什么要使用“forever a = do a; forever a” 我读它是永远开始为1个传入连接分配一个新的listenLoop?换句话说,在我的电脑崩溃之前开始分配新流程?如果有一个永远的循环,我希望它在主要的某个地方?

2) - - - 和* * *是一些尚未实现的RFC我​​在互联网上找不到的东西,有没有用于此的电池?

参考:http://www.fatvat.co.uk/2010/01/web-sockets-and-haskell.html

2 个答案:

答案 0 :(得分:2)

据推测accept是一个阻塞函数调用,因此使用forever不是一个分叉炸弹。至于为什么你这样做,好吧,我认为这是一个相当标准的做法,一个程序监听套接字接受所需数量的连接。

我不是100%确定是否有“Haskell电池”用于代码的缺失部分,但Hackage上肯定有几个包含名称或描述中的websocket;你应该检查一下然后发一个更具体的问题。

答案 1 :(得分:2)

人们可以在Haskell中编写这样的代码。当你调用forkIO函数时,Haskell使用“绿色线程”,这些线程通常在单个线程中运行,直到它们有理由阻塞,此时它们很可能会使用某种线程池机制来获取阻塞的线程上。此功能加上状态事务monad使得在Haskell中设计并发应用程序变得非常容易。

如果你想使用OS线程,那就是forkOS功能。

http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Concurrent.html

此外,GHC的Network.Socket模块尽可能使用非阻塞IO功能,所有这些都是对用户隐藏的。