Edited at

Haskell入門者LT会「ゲスト講演」資料

More than 1 year has passed since last update.


Haskellでソケットプログラミング


はじめに

これは、Haskell入門者LT会のゲスト講演の資料です。Haskell入門ハンズオンのときに、事前資料として公開しておいた部分の復習について、「わかりやすかった」と評判がよかったので、今回も事前に公開することにしました。


何をするか

Webページを開くとき、ブラウザはサーバにHTTP層でGETリクエストを送っている。そのHTTP層は、TCP層のうえで動きます。そのTCP層の直上で、いろいろと試してみる。

あまり「Haskellならでは」といったコードでもなく、Haskellについての知識が増えるわけでもないのですが、今回は「おもしろければそれでいい」ということで。


サンプルコードなど

サンプルコードを用意した。また、できるだけ統一された環境とするために、学習用環境も用意した。gitを使えるかたは以下のようにする。

% git clone https://github.com/YoshikuniJujo/haskell-nyumon-handson

gitを使えないかたは、つぎのアドレスから圧縮ファイルを入手して、展開する。必要に応じてディレクトリ名を変更する。

https://git.io/vQIKd

できたディレクトリに移動しておく。

% 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にあります。ご参考までに。


最後に

これが当日のゲスト講演の内容のすべてです。ハンズオンのときに、「一度やったところは、わかりやすかった。そのあとのところは、ついていくのが大変だった」との意見があったので、今回はすべて事前公開してみました。実験的に。結果的に、「ネタバレでつまらなかった」といった意見があれば、また次の機会の参考にさせてもらいます。

また、「うまく動かない」「わからないところがある」などありましたら、コメントまたは以下にメールをください。

funpaala@gmail.com