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 example of a server that accepts clients, greets them with a welcome message, checks for disconnects 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 qualified Data.ByteString as B (append, null) import Data.ByteString.UTF8 (fromString) -- this is from utf8-string import Control.Monad (forever) import Control.Concurrent (forkIO) -- Accepts clients, spawns a single handler for each one. main :: IO () main = withSocketsDo $ do socket <- listenOn (PortNumber 12345) putStrLn "Listening on port 12345." forever $ do (h, _, _) <- accept socket forkIO (talkTo h) -- Shakes hands with client. If no error, starts talking. talkTo :: Handle -> IO () talkTo h = do request <- shakeHands h case request of Left err -> print err Right _ -> do putFrame h (fromString "Do you read me, Lieutenant Bowie?") putStrLn "Shook hands, sent welcome message." talkLoop h -- Talks to the client (by echoing messages back) until EOF. talkLoop :: Handle -> IO () talkLoop h = do msg <- getFrame h if B.null msg then do putStrLn "EOF encountered. Closing handle." hClose h else do putFrame h $ B.append msg (fromString ", meow.") talkLoop h
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 HandshakeError Request)
- getRequest :: Handle -> IO (Either HandshakeError Request)
- putResponse :: Handle -> Request -> IO ()
- createResponse :: Request -> ByteString
- getFrame :: Handle -> IO ByteString
- putFrame :: Handle -> ByteString -> IO ()
- createToken :: Request -> ByteString
- data Request = Request {}
- data HandshakeError
Documentation
shakeHands :: Handle -> IO (Either HandshakeError 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 HandshakeError
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 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 HandshakeError Request)Source
Reads the client's opening handshake and returns either a Request
based on its contents, or a HandshakeError
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.
createResponse :: Request -> ByteStringSource
Returns an accepting response based on the given Request
. putResponse
uses this function internally.
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. If the writing end of the handle is closed, the function returns an empty ByteString.
putFrame :: Handle -> ByteString -> IO ()Source
Send a strict ByteString. Call this function only after having performed the handshake.
createToken :: Request -> ByteStringSource
Constructs the response token by using the two security keys the and eight-byte token given in the request, as defined by the protocol.
Contains the request details.
data HandshakeError Source
Error in case of failed handshake.