Haskellでソケットプログラミング
はじめに
これは、Haskell入門者LT会のゲスト講演の資料です。Haskell入門ハンズオンのときに、事前資料として公開しておいた部分の復習について、「わかりやすかった」と評判がよかったので、今回も事前に公開することにしました。
何をするか
Webページを開くとき、ブラウザはサーバにHTTP層でGETリクエストを送っている。そのHTTP層は、TCP層のうえで動きます。そのTCP層の直上で、いろいろと試してみる。
あまり「Haskellならでは」といったコードでもなく、Haskellについての知識が増えるわけでもないのですが、今回は「おもしろければそれでいい」ということで。
サンプルコードなど
サンプルコードを用意した。また、できるだけ統一された環境とするために、学習用環境も用意した。gitを使えるかたは以下のようにする。
% git clone https://github.com/YoshikuniJujo/haskell-nyumon-handson
gitを使えないかたは、つぎのアドレスから圧縮ファイルを入手して、展開する。必要に応じてディレクトリ名を変更する。
できたディレクトリに移動しておく。
% cd haskell-nyumon-handson/beginnerLt/
まずはファイル入出力
% cat hello.txt
Hello, world!
% stack ghci
> :module System.IO
> h <- openFile "hello.txt" ReadMode
> hGetLine h
"Hello, world!"
> hClose h
> h <- openFile "foo.txt" WriteMode
> hPutStrLn h "bar"
> hClose h
> :quit
% cat foo.txt
bar
Webページに接続
つぎは、Webページに接続してみる。
% stack ghci --package network
> :module Network
> :module + System.IO
> h <- connectTo "skami.iocikun.jp" $ PortNumber 80
> hPutStrLn h "GET / HTTP/1.1"
> hPutStrLn h ""
> hGetLine h
"HTTP/1.1 200 OK\r"
ファイルの入出力と、おなじように書ける。
HTTPのGETリクエストを出したら、HTTP 200 OKがかえってくる。
サーバを立てる
「手作業、大好き!!」人力サーバを立ててみよう。
> s <- listenOn $ PortNumber 4492
> (h, _, _) <- accept s
acceptによって作られる動作は、クライアントからの接続を待つ。ブラウザを開いて以下のアドレスをうちこもう。
http://localhost:4492
対話環境にもどって
> hGetLine h
"GET / HTTP/1.1\r"
> hPutStrLn h "HTTP/1.1 200 OK"
> hPutStrLn h "Content-Type: text/plain"
> hPutStrLn h "Content-Length: 5"
> hPutStrLn h ""
> hPutStrLn h "hello"
これで、ブラウザにhelloと表示される(はず)。
きのこ、たけのこ総選挙
最後は「きのこ、たけのこ総選挙」でしめる。現在、「きのこ、たけのこ総選挙」サーバを立ち上げたままにしてあるので、各自クライアントを書いて、選挙に参加しよう。(ただし、結果はサーバを落とすたびに0, 0にリセットされますが)
「きのこ、たけのこ総選挙」クライアント
つぎのようなクライアントを書きます。
import System.IO
import Network
main :: IO ()
main = do
h <- connectTo "skami.iocikun.jp" $ PortNumber 4492
hPutStrLn h "Yoshio"
hPutStrLn h "kinoko"
hGetLIne h >>= putStrLn
hClose h
Yoshioのところは各自の名前(日本語不可)に置き換えて、kinokoのところは場合によってtakenokoに置き換えてください。サンプルコードとしてkinoko.hsやtakenoko.hsが用意してあります。
コンパイルするのがめんどうなら、つぎのようにして走らせます。
% stack ghc -- -fno-warn-tabs -e main kinoko.hs
kinoko: 2 takenoko: 3
当日はサーバのほうの出力もお見せします。また、サーバのソースコードはkt.hsにあります。ご参考までに。
最後に
これが当日のゲスト講演の内容のすべてです。ハンズオンのときに、「一度やったところは、わかりやすかった。そのあとのところは、ついていくのが大変だった」との意見があったので、今回はすべて事前公開してみました。実験的に。結果的に、「ネタバレでつまらなかった」といった意見があれば、また次の機会の参考にさせてもらいます。
また、「うまく動かない」「わからないところがある」などありましたら、コメントまたは以下にメールをください。