A socker wrapper that makes the IO of sockets much cleaner.
The idea of a BufferedSocket
is that reading from a network socket should be really easy and handy. BufferedSockets is an attempt to do just that whilst beeing space-time efficient. Having "in app" buffers also makes it easy for the buffered socket to read data without taking the data out of the buffer thus giving us the ability to look for patterns and read exess data without having to "take out of the reading queue".
BufferedSocket
A wrapper for webSockets
This package is made to make reading and writing from network sockets easy in haskell.
To make a socket you need three things.
A socket made from the Network package (BufferedSockets doesn't meddle with your configuration so you have to do all this yourself)
Descide output buffer size
Descide input buffer size
(party like it's 1969)
this is done with the following function:
makeBufferedSocket :: (Socket, SockAddr) -> InputBufferSize -> OutputBufferSize -> IO BufferedSocket
The main functions for read and write:
Reading:
read :: BS.BufferedSocket -> IO r
The standard read is made to ready any basic data values. This is amongst Word8 to Word64 and Int8 to Int64
readString :: BS.BufferedSocket -> Int -> IO s
Thea readString funtcion can read both lazy and strict bytestrings. But you need to provide the number of bytes to read.
To read any other kind of data is is reccomended to still use these functions. And then use decoding methods to get the data format you want.
readToByte :: BufferedSocket -> Word8 -> IO ByteString
readToByteMax :: BufferedSocket -> Word8 -> MaxLength -> IO (Maybe ByteString)
readToByteString :: BufferedSocket -> ByteString -> IO ByteString
readToByteStringMax :: BufferedSocket -> ByteString -> MaxLength -> IO (Maybe ByteString)
The above functions are made to scan the input buffer for specific bytes. All of them of course reads more data from the network if necesarry However it is reccomended to use the "Max" verions of the functions as they put a limit to how much data may be read
Writing:
send :: BS.BufferedSocket -> s -> IO ()
Sends any basic data type and both lazy and strict ByteStrings If you wish to send any other kind of data use encoding methods for the data type.
flush :: BufferedSocket -> IO ()
Data is not sent to the network unless:
- The writing buffer is full
- Flush is called
Buffer functionalities
Input
The buffers are made to work is a fairly standard way. Every time we read from the socket the socket first checks the buffer if data is available. If it is it will just aquire the data from the buffer. If not then it will access the network and attempt to read for the ammount of bytes that are available in the buffer. If not enthough space is available the first step is to see if clearing the offset will grant enoguh space. If not it will allow the data to be saved elsewhere.
Output
Is much simpler then Input. Simply puts the bytes together before sending. The actaul sending of data will only happend once the buffer is full OR the flush function is called
Example code:
here under is some example code. Warning this is pretty pointless code!!!
{-# LANGUAGE OverloadedStrings #-}
import qualified Network.Socket as NS -- NS for "native socket"
import qualified BufferedSocket as BS
import qualified Data.ByteString as B
testServerPort = 1337
testHost = "localhost"
testServerMaxConnections = 1
bufferSize = 1024 * 10
-- This is an example how to make a TCP server in haskell
-- Keep in mind that this is a pretty supid server
makeTestTcpServer:: (BS.BufferedSocket -> IO ()) -> IO ()
makeTestTcpServer thunk = NS.withSocketsDo $ do
-- creates a tcp socket
serverSock <- NS.socket NS.AF_INET NS.Stream 0
-- Binds the socket to serve at address
NS.bindSocket serverSock (NS.SockAddrInet testServerPort NS.iNADDR_ANY)
NS.listen serverSock testServerMaxConnections
socketData@(subSock,subSockaddr) <- NS.accept serverSock
serverBSock <- BS.makeBufferedSocket socketData bufferSize bufferSize
thunk serverBSock
NS.sClose serverSock
main = makeTestTcpServer $ \bSock ->
BS.send bSocket ("Hello world!" :: B.ByteString)