-
Last changed Time-stamp: <2001-12-11 20:15:43 xtof>
simple echo client
you need Meurig Sage Regular expression library for Haskell
available from: http://www.dcs.gla.ac.uk/~meurig/regexp/
compile and link with (ghc-5.02.1):
ghc -syslib net -syslib data -syslib Regexp -c -o EchoClient.o EchoClient.hs
ghc -syslib net -syslib data -syslib Regexp -o EchoClient EchoClient.o
module Main (main) where
import IO
import System
import SocketPrim
import BSD
-
Meurig Sage's regexp library is not part of the ghc-5.02.1 libraries
get the library for Haskell 98 from http://www.dcs.gla.ac.uk/~meurig/regexp/
follow the instructions how to build the library
if you want to use the library with ghc's -syslib option,
you have to add it to your ghc distribution using ghc-pkg
otherwise use the ghc option
-iPATH_TO_REGEXP_HI_FILES for compiling and
-LPATH_TO_REGEXP_LIBRARY -lRegexp for linking
import Regexp
data Consts
= Consts{ address :: String,
portnum :: Int }
defaults :: Consts
defaults
= Consts { address = "localhost",
portnum = 7 }
-
i found the following on the Programming Language Examples Alike Cookbook
(PLEAC homepage) http://pleac.sourceforge.net/
(=~) :: String -> String -> Bool
(=~) s re = let matchresult = searchS re [] s in
matchedAny matchresult
isPortNumber :: String -> Bool
isPortNumber s
| s =~ "^\\d+$" = True
| otherwise = False
isAddress :: String -> Bool
isAddress s
| s =~ "^[a-z.]+$" = True
| otherwise = False
-
if portnumber was given on command-line return it
otherwise return portnumber from defaults
extractPort :: [String] -> IO Int
extractPort args
=
case [ a | a <- args, isPortNumber a ] of
([] ) -> return (portnum defaults)
(x:_) -> return ((read x)::Int)
-
if hostname was given on command-line return it
otherwise return hostname from defaults
extractAddr :: [String] -> IO String
extractAddr args
=
case [ a | a <- args, isAddress a ] of
([] ) -> return (address defaults)
(x:_) -> return x
processCmlArgs :: IO (String, Int)
processCmlArgs
= do
args <- getArgs
port <- extractPort args
addr <- extractAddr args
return (addr, port)
gethostbyname:: String -> IO HostAddress
gethostbyname hostname
= do
hostentry <- getHostByName hostname
return (hostAddress hostentry)
-
retrive the value of the TCP protocol number
convert symbolic hostname into a packt IP address
create a strem-style Internet-domain socket (local communication endpoint)
connect to the remote host (remote communication endpoint)
convert socket to a handle
connectto :: String -> Int -> IO (Handle, Socket)
connectto hostname port
= do
protocolnum <- getProtocolNumber "tcp"
ipaddress <- gethostbyname hostname
sock <- socket AF_INET Stream protocolnum
connect sock (SockAddrInet (fromIntegral port) ipaddress)
handle <- socketToHandle sock ReadWriteMode
return (handle, sock)
disconnect :: Handle -> Socket -> IO ()
disconnect handle sock
= do
hClose handle
sClose sock
loop :: Handle -> IO ()
loop handle
= do
l <- hGetLine stdin
sendLine l handle
r <- reciveLine handle
case r of
([]) -> return ()
(_:_) -> do
hPutStrLn stdout r
loop handle
sendLine :: String -> Handle -> IO ()
sendLine string handle
= do
hPutStrLn handle string
reciveLine :: Handle -> IO String
reciveLine handle
= do
l <- hGetLine handle
return l
main :: IO ()
main
= do
(hostname, port) <- processCmlArgs
(handle, sock) <- connectto hostname port
hSetBuffering handle LineBuffering
loop handle
disconnect handle sock