Programming:Network

Programming:Network

とりあえずの Echo サーバ

\begin{code}
module Main where

import Control.Concurrent
import Network
import System.IO

type Service = String -> String

port :: PortNumber
port = 8888

echo :: Service
echo = id

main :: IO ()
main = server port echo

server :: PortNumber -> Service -> IO ()
server p sc = withSocketsDo $ listenOn (PortNumber p) >>=  serve sc

serve :: Service -> Socket -> IO ()
serve sc sock =  accept sock >>= forkIO . service sc >> serve sc sock

service :: Service -> (Handle, HostName, PortNumber) -> IO ()
service sc (h,_,_) = hSetBuffering h LineBuffering >> loop h sc

loop :: Handle -> Service -> IO ()
loop h sc =  hIfEOF h (return ()) $ hGetLine h >>= hPutStrLn h . sc >> loop h sc

hIfEOF :: Handle -> IO a -> IO a -> IO a
hIfEOF h t e = hIsEOF h >>= \ eof -> if eof then t else e

\end{code}

とりあえずのEchoサーバ(低レベルAPI, 非関数プログラミング志向, 最低仕様)

私の環境では上記のHigh Level API利用だとservname no supportedになる。 アドレス解決ができない模様なのでLow Level APIを叩いてみた。cut-sea:2008/06/05 05:24:09 JST

import Network.Socket

server sv = do s0 <- sock0
               bindSocket s0 addr0
               listen s0 5
               (s1,a1) <- accept s0
               sv s1
    where
    sock0 = socket AF_INET Stream 0
    addr0 = SockAddrInet 8888 0x0100007f -- 127.0.0.1:8888

echo s =  do (rcv, len, addr) <- recvFrom s 2048
             send s rcv
             echo s

main :: IO a
main = server echo

なぜかIP Addressの指定が1.0.0.127的にしないと127.0.0.1にならない。
もしかしてBig/Little Endianがおかしい?(pkgsrcからbuildしたghcなんだけど)

正直流れが見えるまで、何故こんなAPIになってるのかムカついてたんだけど…

ステップバイステップでないと書けない子なので、

sock0 = socket AF_INET Stream 0
addr0 = SockAddrInet 8888 0x0100007f -- 127.0.0.1:8888
                :
                :

みたいな調子でロードしてはsock0やらaddr0やら確認してた。 するとbindとlistenのところでハマって、 ようやくsocketの返すのがIO Socketという風にIOモナドに包まれている理由が分った。 なーる。


Last modified : 2008/06/11 14:10:52 JST