Skip to content

Instantly share code, notes, and snippets.

@chrisdew
Created June 15, 2012 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisdew/2937090 to your computer and use it in GitHub Desktop.
Save chrisdew/2937090 to your computer and use it in GitHub Desktop.
A working client to server sending of a message in protobuf format.
module Main where
import Network.Socket hiding (send, sendTo, recv, recvFrom)
import Network.Socket.ByteString
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString as BS
import Text.ProtocolBuffers.WireMessage (messageGet)
import AddressBookProtos.Person
main :: IO ()
main = do
withSocketsDo $ do
sock <- socket AF_INET Datagram 0
bindSocket sock (SockAddrInet 4567 iNADDR_ANY)
socketRx sock
mesgToPerson :: LBS.ByteString -> Either String (Person, LBS.ByteString)
mesgToPerson mesg = messageGet mesg
strictToLazyBS :: BS.ByteString -> LBS.ByteString
strictToLazyBS x = LBS.fromChunks [x]
socketRx :: Socket -> IO ()
socketRx sock = do
putStrLn "waiting for packet"
(mesg, _) <- Network.Socket.ByteString.recvFrom sock 1500
putStrLn "received packet"
putStrLn "-------------------"
putStrLn $ show mesg
putStrLn "-------------------"
let eitherPerson = mesgToPerson (strictToLazyBS mesg)
case eitherPerson of
Right (person, _) -> putStrLn $ show person
Left err -> (putStrLn "Failed to parse.") >> (putStrLn err)
putStrLn "-------------------"
socketRx sock
module Main where
import Network.Socket hiding (send, sendTo, recv, recvFrom)
import Network.Socket.ByteString
import Text.ProtocolBuffers.Header (uFromString)
import Text.ProtocolBuffers.WireMessage (messagePut)
import Data.ByteString as BS
import Data.ByteString.Lazy as LBS
import Data.Sequence (fromList)
import AddressBookProtos.Person
import AddressBookProtos.Person.PhoneNumber
import AddressBookProtos.Person.PhoneType
opensocket :: HostName -> String -> IO (Socket, AddrInfo)
opensocket hostname port =
do -- Look up the hostname and port. Either raises an exception
-- or returns a nonempty list. First element in that list
-- is supposed to be the best option.
addrinfos <- getAddrInfo Nothing (Just hostname) (Just port)
let serveraddr = Prelude.head addrinfos
-- Establish a socket for communication
sock <- socket (addrFamily serveraddr) Datagram defaultProtocol
-- Save off the socket, and server address in a handle
return (sock, serveraddr)
john :: Person
john = Person {
AddressBookProtos.Person.id = 1234,
name = uFromString "John Doe",
email = Just $ uFromString "jdoe@example.com",
phone = fromList [
PhoneNumber {
number = uFromString "555-4321",
type' = Just HOME
}
]
}
johnLBS :: LBS.ByteString
johnLBS = messagePut john
lazyToStrictBS :: LBS.ByteString -> BS.ByteString
lazyToStrictBS x = BS.concat $ LBS.toChunks x
main::IO()
main = do (sock, addr) <- opensocket "localhost" "4567"
_ <- sendTo sock (lazyToStrictBS johnLBS) (addrAddress addr)
return ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment