ネットワークプログラミング(サーバー編)
そろそろネットワークのプログラムを書いてみようと思ったので、echo サーバを書いてみた。
意外に簡単に書けてしまった。 C しか知らなかった頃は、頑張って scoket, bind, listen ... とかシステムコール呼び出してたけど(あと引数の構造体を作るのが面倒だった記憶が)、もうそんなことをしなくてもいいんだ。
コードはこんな感じ。セッションが終了すると、サーバも終了してしまうが、まあ、そこはおいおいということで。
import Network import System.IO import System.Environment import Control.Applicative main :: IO () main = do port <- (!! 0) <$> getArgs sock <- listenOn . PortNumber . fromInteger $ read port (handle, _, _) <- accept sock hSetBuffering handle LineBuffering request <- hGetContents handle hPutStr handle request sClose sock
驚いたのが、
request <- hGetContents handle hPutStr handle request
の部分。バッファリングは行単位にしているので、hGetContents で得られるデータは 1 行だけ。hGetContents の後に hPutStr でその 1 行を出力している。
なので、このエコーサーバは 1 行のみ結果を返して終了するだろうと思っていたのだが、実際は違った。セッションが終了するまで、何行でもエコーを返してくる。しかも、クライアントが 1 行入力する度にサーバも 1 行返してくる(セッション終了時に、今まで入力した行をまとめて返してくるということではない)。
遅延評価ってやつかしら?すごいな。
ちなみに、ログを出力しようと、hGetContents handle と hPutStr handle request の間に putStrLn を挟んだら期待通りには動かなくなった。まともなサーバにするにはこんなコードではダメ(わかってるけど)。