A library for creating WebSocket-capable servers, where the implemented protocol is defined here: http://is.gd/eSdLB.
This library was only tested with Chromium 7.* and Firefox 4.*, currently doesn't implement the entire WebSocket protocol, will never implement older versions of the WebSocket protocol and is a work in progress.
How do you use this library? Here's how:
- Get a
Handle
to your connected client. - Perform the initial handshake with
shakeHands
(orgetRequest
andputResponse
). - Send and receive strict bytestrings with
putFrame
andgetFrame
.
And here's a short, complete example of a server that accepts clients, greets them with a welcome message and replies to all messages by echoing them back with an appended meow:
import Network.WebSockets (shakeHands
,getFrame
,putFrame
) import Network (listenOn, PortID(PortNumber), accept, withSocketsDo) import System.IO (Handle, hClose) import Data.ByteString (append) import Data.ByteString.UTF8 (fromString) -- this is from utf8-string import Control.Monad (forever) import Control.Concurrent (forkIO) main :: IO () main = withSocketsDo $ do socket <- listenOn $ PortNumber 12345 putStrLn "Listening on 0.0.0.0:12345." forever $ do (h, _, _) <- accept socket forkIO $ talkToClient h talkToClient :: Handle -> IO () talkToClient h = do request <-shakeHands
h case request of Left error -> putStrLn error >> hClose h Right req -> doputFrame
h . fromString $ "滴水之恩当以涌泉相报<br>" ++ show req forever $ do msg <-getFrame
hputFrame
h . append msg $ fromString ", MEOW!"
The example above will suffice if you wish to accept any WebSocket-capable client, regardless of its origin or target. It won't suffice if you have to filter the incoming clients by the contents of their requests. For that, you can use getRequest
and putResponse
, which allow you to inspect the request details before you send back a response, if any.
If you have any suggestions, bug reports and/or fixes, feel free to send them to mailto:sinisa@bidin.cc.
- shakeHands :: Handle -> IO (Either String Request)
- getRequest :: Handle -> IO (Either String Request)
- putResponse :: Handle -> Request -> IO ()
- getFrame :: Handle -> IO ByteString
- putFrame :: Handle -> ByteString -> IO ()
- reqHost :: Request -> String
- reqPath :: Request -> String
- reqOrigin :: Request -> String
- reqLocation :: Request -> String
- data Request
Documentation
shakeHands :: Handle -> IO (Either String Request)Source
Accept and perform a handshake, no matter the request contents.
As long as the request is well-formed, the client will receive a response saying, essentially, "proceed". Use this function if you don't care who you're connected to, as long as that someone speaks the WebSocket protocol.
The function returns either a String in case of error, or a Request
on success. The Request
is returned purely for logging purposes, since the handshake has already been executed. Use this function immediately after establishing the WebSocket connection.
If you wish not to blindly accept requests but to filter them according to their contents, use the getRequest
and putResponse
functions.
getRequest :: Handle -> IO (Either String Request)Source
Reads the client's opening handshake and returns either a Request
based on its contents, or a String in case of an error.
putResponse :: Handle -> Request -> IO ()Source
Sends an accepting response based on the given Request
, thus accepting and ending the handshake.
getFrame :: Handle -> IO ByteStringSource
Receive a strict ByteString. Call this function only after having performed the handshake. This function will block until an entire frame is read.
putFrame :: Handle -> ByteString -> IO ()Source
Send a strict ByteString. Call this function only after having performed the handshake.
reqLocation :: Request -> StringSource
Returns the requested location. Equal to (\r -> "ws://" ++ reqHost r ++ reqPath r)
.