\documentclass{howto}

%\title{Socket Programming HOWTO}
\title{ソケットプログラミング HOWTO}

\release{0.00}

\author{Gordon McMillan}
\authoraddress{\email{gmcm@hypernet.com}}

\begin{document}
\maketitle

\begin{abstract}
\noindent
ソケットはほとんどどこでも使われていますが、とくに頻繁に誤解されている
技術の一つでもあります。
このドキュメントはソケットに対する10,000フィートからの概観です。
これはチュートリアルではありません - このドキュメントを読んだ後でも
実際に使えるようになるまでにまだしないといけないことがあるでしょう。
この文書は詳細な点はカバーしません (詳細な解説はたくさんあります) が、
私はこの文書が、あなたがきちんとソケットを扱うための十分な背景知識を
提供できればと思います。


この文書は次の Python HOWTO ページから取得できます。
\url{http://www.python.org/doc/howto}

\end{abstract}

\tableofcontents

\section{ソケット (socket)}

ソケットはほとんどどこでも使われていますが、とくに頻繁に誤解されている
技術の一つでもあります。
このドキュメントはソケットに対する10,000フィートからの概観です。
これはチュートリアルではありません - このドキュメントを読んだ後でも
実際に使えるようになるまでにまだしないといけないことがあるでしょう。
この文書は詳細な点はカバーしません (詳細な解説はたくさんあります) が、
私はこの文書が、あなたがきちんとソケットを扱うための十分な背景知識を
提供できればと思います。

ここではINETソケットだけを扱います。INETソケットは実際に使われて
いるソケットの少なくとも99\%をしめています。
そして、STREAM ソケットだけを扱います - あなたが自分が何をして
いるのかを本当に理解しているのでなければ(その場合このHOWTOは
あなた向けではありません!)、あなたはSTREAMソケットでほかの
ソケットよりも良い振る舞いとパフォーマンスを得られるでしょう。
どうやってブロッキングソケット、非ブロッキングソケットを扱うか
についてのヒントを述べると同時に、ソケットとはいったい何なのかを
明瞭にしたいと思います。
ただし、まずはブロッキングソケットから始めます。非ブロッキング
ソケットを扱う前に、ブロッキングソケットがどのように動作するかを
知る必要があります。

ソケットについて理解するときの問題の一つは、"ソケット"が文脈によって
微妙に異なるいろいろな意味を持つことです。
なので、まずは "クライアント (client)" ソケット (通信の端) と、 
"サーバー (server)" ソケット(どちらかというと電話交換手のようなもの)
の違いをはっきりさせましょう。
クライアントアプリケーション (たとえばあなたのブラウザ) は、
"クライアント"ソケット だけを利用します。
それに対して、Webサーバーは "サーバー" ソケットと "クライアント"
ソケットの両方を利用します。

\subsection{歴史}

IPC (\emph{プロセス間通信 (Inter Process Communication)} のいくつかの形の中で、
ソケットはダントツでポピュラーです。
どんなプラットフォームにおいても、より速いIPCの方法があるかもしれませんが、
クロスプラットフォームな通信ではソケットの独壇場です。

ソケットはBerkeley大学で、BSD (Unixの一種) の一部として考え出されました。
そして、インターネットと共に急速に広まっていきました。
その理由は、INETとソケットの組み合わせが、世界中の任意のマシンと通信するのを
(少なくとも他の方法に比べると) 信じられないくらい簡単にしたからです。

\section{ソケットを作る}

あなたがリンクをクリックしてこのページにくるとき、あなたのブラウザは
おおまかに言って次のようなことをしています:

\begin{verbatim}
    #INET, STREAMing ソケットを作る
    s = socket.socket(
        socket.AF_INET, socket.SOCK_STREAM)
    #webサーバーの80番ポート (httpの一般的なポート) につなぐ
    #訳注: 繋いでるサーバーはたぶんこの文章の原文があった場所です。
    s.connect(("www.mcmillan-inc.com", 80))
\end{verbatim}

\code{connect}が完了したとき、ソケット \code{s} はこのページのテキストに
対するリクエストを送ることができます。
ソケットはその後リクエストの返信を読み、破棄されます。そう、破棄するのです。
クライアントソケットは通常、一回のやりとり (もしくは、連続する数個のやりとり)
のためだけに使います。

Webサーバーで起こっていることはもう少し複雑です。まず、webサーバーは"サーバーソケット"を
作ります。

\begin{verbatim}
    # INET, STREAMing socket を作る
    serversocket = socket.socket(
        socket.AF_INET, socket.SOCK_STREAM)
    #そしてソケットを公開ホストの
    # well-known ポートにbindする
    serversocket.bind((socket.gethostname(), 80))
    #サーバーソケットになる
    serversocket.listen(5)
\end{verbatim}

２つのことに気づきます: \code{socket.gethostname()} を使っているので、
ソケットは外の世界から見えるようになります。
代わりに \code{s.bind(('', 80))} や \code{s.bind(('localhost', 80))} や
\code{s.bind(('127.0.0.1', 80))} の様にすると、サーバーソケットはできるの
ですが、それは同じマシンからしか見えなくなります。

次に注意しなければならない点は、小さい番号のポートはよく "well known" 
サービス (HTTP, SNMP 等) のために予約されていることです。
試しに使ってみる場合は、大きい４桁の番号を使ってください。

最後に、\code{listen} の引数が、ソケットライブラリに、コネクションを
はじく前に、５個までのコネクションリクエストをキューイングするように
指定していることに注目してください。
残りのコードを適切に書けば、これは十分な量のはずです。

はい、今までで80番ポートをlistenしているサーバーソケットを用意できました。
次はWebサーバーのメインループに入ります: 

\begin{verbatim}
    while 1:
        #外部からのコネクションを受け付ける
        (clientsocket, address) = serversocket.accept()
        #クライアントソケットを使って何かする
        #今回の場合、スレッドで並列化されたサーバーのふりをする
        ct = client_thread(clientsocket)
        ct.run()
\end{verbatim}

このようなループを動作させるための、一般的な３つの方法があります -
\code{clientsocket} を thread に渡して(dispatch)スレッドであつかう、
\code{clientsocket} を扱う新しいプロセスを作る、
ノンブロッキングソケットを使うようにこのアプリの構造を変えて、
\code{select}を使って、アクティブな\code{clientsocket}と\code{serversocket}を
多重化する。最後の方法については後で話します。
ここで理解してほしい重要なポイントは、 サーバーソケットはこれで
\emph{すべて} だということです。何も送信しません。何も受信しません。
ただ "クライアント"ソケットを作るだけです。
\emph{他の}クライアントソケットがbindしていたホストとポートに\code{connect()}
してきたときに、各\code{clientsocket}が作られます。
\code{clientsocket}が作成されると、すぐに他のコネクションのlistenに
戻ります。 ２つの"クライアント"がそれぞれ自由におしゃべりできます。
会話がおわったあと、そのソケットに動的に割り当てられていたポートは回収されます。

\subsection{IPC} もし一つのマシンの中の二つのプロセスの間で高速なIPCが
必要なら、そのプラットフォームが提供する共有メモリの類を調べるべきです。
共有メモリとロックかセマフォを使うシンプルなプロトコルは、圧倒的に高速な
技法です。

もしソケットを使うと決めたなら、"サーバー"ソケットを\code{'localhost'}に
bindしてください。 ほとんどのプラットフォームにおいて、こうすることで
いくつかのネットワークレイヤに関するコードをショートカットするので、
確実に少し速くなります。

\section{ソケットを使う}

まず注目するのは、Webブラウザの"クライアント"ソケットとWebサーバーの
"クライアント"ソケットは対等だということです。
つまり、これは "peer to peer" 通信です。
別の言い方をすれば、\emph{通信における礼儀作法が何かについては設計者の
あなたが決める必要があります。}
普通は、ソケットに\code{connect}することが通信の開始であり、リクエストを
送るなりサインインしたりします。
しかし、これは設計上の決定であり、ソケットのルールではありません。

通信するのに使う動詞が二セットあります。\code{send}と\code{recv} を使うか、
"ファイル"のように\code{read}と\code{write}を使うことができます。
後者は現在のJavaと同じです。
ここでは後者についてはおいておきますが、ソケットを \code{flush} しないと
いけないことについてだけは注意しておきます。
"ファイル"にはバッファがあり、よくあるミスは何かを \code{write} したあとに、
すぐに返信を \code{read} してしまうことです。\code{flush} をしないければ、
返事を永遠に待つことになるかもしれません。リクエストがまだ自分の出力バッファ
にあるからです。

\code{send} と \code{recv} をネットワークバッファに対して行ったとき、
ソケットのブロックという大きなつまづきポイントがあります。
それらはネットワークバッファに対する操作に注目しているので、
あなたが送ろうとしたすべてのbytesを扱うとは限りません。
一般的に、それらの関数は割り当てられたネットワークバッファを(\code{send}で)
一杯にしたときか、(\code{recv})で空にした時点で戻ってきます。
そして、扱ったバイト数を返します。
送受信したいメッセージ全体が扱われるまで、\emph{あなたが}なんども
繰り返してそれらを呼び出す必要があります。

\code{recv}が0を返したときは、相手側がコネクションを閉じた(あるいは
閉じかけている)ことを意味します。
このコネクションからはもう何も受信できません。
でも、送信は正常にできるかもしれません; このことについては次のページで
話します。

HTTPのようなプロトコルは1つのソケットを一つの転送のためだけに利用します。
クライアントはリクエストを送り、返信を読みます。それだけで、ソケットは
捨てられます。これは、クライアントは返信がどこで終わったかを0byte受信で
判別することができることを意味します。

しかし、あなたがソケットを次の転送のために使い回そうとしたとき、
\emph{"EOT" (End of Transfer) の様なものはソケットには存在しない}
ことを認識する必要があります。
繰り返します: ソケットのに対する \code{send} や \code{recv} が0を返した
とき、そのコネクションは既に壊れています。
コネクションが壊れて\emph{いなかった}場合、あなたはずっと \code{recv} を
待ち続けることになるでしょう。ソケットは(今のところ)読み込むデータが存在
しないという事をあなたに\emph{教えない}からです。
ソケットを使い回す事について少し考えれば、ソケットの本質を認識するように
なるでしょう: \emph{メッセージは固定長か}(おぇっ)、\emph{区切られているか}(はぁ)、
\emph{自分でメッセージ長を示すか}(だいぶマシ)、\emph{コネクションの
シャットダウン(訳注: shutdownについては後述)によって終わらなければ
なりません}。
どの方法を選択するかはあなた次第です（ただし、方法の優劣はあります）。


コネクションを終わらせたくないと仮定すると、一番シンプルな方法は
固定長メッセージです:

\begin{verbatim}
class mysocket:
    '''デモ用クラスのみ
      - 効率ではなく明瞭さのためのコード.
    '''

    def __init__(self, sock=None):
	if sock is None:
	    self.sock = socket.socket(
		socket.AF_INET, socket.SOCK_STREAM)
	else:
	    self.sock = sock

    def connect(self, host, port):
	self.sock.connect((host, port))

    def mysend(self, msg):
	totalsent = 0
	while totalsent < MSGLEN:
	    sent = self.sock.send(msg[totalsent:])
	    if sent == 0:
		raise RuntimeError, \\
		    "socket connection broken"
	    totalsent = totalsent + sent

    def myreceive(self):
	msg = ''
	while len(msg) < MSGLEN:
	    chunk = self.sock.recv(MSGLEN-len(msg))
	    if chunk == '':
		raise RuntimeError, \\
		    "socket connection broken"
	    msg = msg + chunk
	return msg
\end{verbatim}

この送信用のコードはだいたいのメッセージスキームで利用できます -
Pythonで文字列を送る、そして \code{len()} を使って(文字列の中に文字
\code{\e 0} が含まれていても)文字列の長さを知ることができる。
受信用のコードは大抵もう少し複雑になります。 (そしてC言語でも、
この方法はメッセージの中に文字 \code{\e 0} が入っているために
\code{strlen} が使えないことをのぞくと悪くないです。)


一番簡単な改良は、メッセージの最初の文字でメッセージのタイプを表す様に
して、メッセージのタイプによって長さが決まるようにすることです。
その場合、二つの \code{recv} が必要です - 最初は少なくとも最初の
文字を受信してメッセージの長さを知るため、二つ目は残りを受信するまでの
ループの中です。
デリミタを使う方式を採用するなら、不定なチャンク(chunk)サイズ
(4096 か 8192 がネットワークのバッファサイズによく合います)を受信して、
デリミタを受信したかどうかスキャンして調べます。

気をつけないといけないやっかいな問題を一つ: もし通信プロトコルが
次から次へといくつものメッセージを返信なしに送ることができるもので、
あなたが \code{recv} に適当なチャンクサイズを指定したら、次の
メッセージの先頭まで読み込んでしまいます。その場合、次のメッセージを
置いておいて、必要になるまで保存しておく必要があるでしょう。


メッセージの先頭にその長さをつける(ここでは数字５文字としておこう)と、
より難しくなります。信じられないかもしれないけど、一回の \code{recv} で５文字を
取得できないこともあるからです。
試しでやってる間はそんな現象は起きないかもしれないけど、ネットワーク負荷が
高い環境に持って行くと、二つの \code{recv} ループ
- 一つ目は長さを決めるため、二つ目はデータ部分の読み込み -
を使わないかぎりは簡単に壊れてしまいます。
やっかいなことに、\code{send} を使うときも全てを1-passではできません。
そして、あなたはこれを読んでいたとしても、いつかはこの罠にハマるでしょう！

スペースと、あなたの個性（と、私の競争力の維持）のために、のこりの
改良は読者への演習としておきます。

\subsection{バイナリデータ}

ソケットを通してバイナリデータを完全に送ることができます。その場合の
よくある問題点は、すべてのマシンがバイナリデータに対して同じフォーマットを
利用しているわけでは無いことです。
たとえば、モトローラのチップは16bit整数で1を2バイト 00 01 (16進) で表し、
IntelとDECではバイトの順序が逆転して同じ1が 01 00 になります。
ソケットライブラリは16bitと32bitの整数を変換する関数を持っています -
\code{ntohl, htonl, ntohs, htons} です。"n"は \emph{network} を意味し、
"h" は \emph{host} を意味し、 "s" は \emph{short} "l" は \emph{long} を
意味します。
ネットワーク バイトオーダーとホスト バイトオーダーが一致する環境では、
これらの関数は何もしません。バイト順が逆になっているマシンでは、
これらの関数はバイト順を適切に入れ替えます。

現代の32bitマシンでは、バイナリデータのascii表現がバイナリ表現よりも
小さくなることがよくあります。long型の値がすべて0や1のとき、
バイナリ表現が4バイトなのに対して文字列 "0" は2バイトで済むからです。
もちろん、この方法は固定長メッセージには適しません。よく考えて
決めてください。

%\section{Disconnecting}
\section{切断する}

厳密に言えば、ソケットを \code{close} するまえに \code{shutdown} を
使うべきです。\code{shutdown} は相手側ソケットへのヒントです。
\code{shutdown} に渡す引数によって、「もうなにも送らないけど、
まだ受信してるよ」もしくは「もう受信やめた、バイバイ！」という
意味になります。
プログラマがこの礼儀を無視することが多かったので、ほとんどのソケット
ライブラリでは普通 \code{close} は \code{shutdown(); close()} 
と同じになっています。
なので、ほとんどの場合、明示的に\code{shutdown}する必要はありません。


\code{shutdown} が役に立つ一つの方法は、HTTPのような通信です。
クライアントはリクエストを送信した後 \code{shutdown(1)} します。
これは、サーバーに「送信終了、お返事待ってます」と伝えます。
サーバーは0バイトを受信して、"EOF" を検出することができます。
それにより、リクエストが完了したと見なすことができます。
そしてサーバーは返事を返します。\code{send} が正常に完了したなら、
本当にクライアントが受信を待っていたということです。

Pythonはさらに進んだ自動shutdown機能を持っていて、ソケットが
GC（ガベージコレクト) されたときに、必要であれば \code{close} します。
しかし、これに頼るのは非常に悪い習慣です。
もしソケットを \code{close} しないままおいておくと、相手側は、
あなたが遅くなっただけかもしれないと思いずっと待ち続けます。
完了したときは \code{close} \emph{してください。}



%\subsection{When Sockets Die}
\subsection{ソケットが死ぬとき}

多分、ブロッキングソケットにおいてもっとも悪いケースは、相手側が \code{close}
せずに落ちてしまったときです。
あなたのソケットはハングしたようになります。SOCKSTREAMは信頼できる
プロトコルで、コネクションをあきらめるまでに長い長い間待ちます。
もしあなたがスレッドを使っているのであれば、スレッドが死んだように
なります。あなたにできることは何もありません。
ロックを取得したままブロッキングreadするなどのバカをしない限り、
そのスレッドはそれ以上のリソースを消費したりはしません。
スレッドをkill\emph{してはいけません} - その理由の一つは、スレッドが
プロセスより効率が良い理由がリソースの自動回収に関するオーバーヘッドを
避けられることだからです。言い換えると、スレッドをkillすると、
プロセス全体がめちゃくちゃになります。


%\section{Non-blocking Sockets}
\section{非ブロッキングソケット}

以上のことを理解すれば、あなたはソケットを扱うメカニックとして知らなければ
ならないほとんどのことを知っている事になります。
このまま、同じような方法を正しく行えば、あなたのアプリはほとんど完璧でしょう。


Pythonでは、 \code{socket.setblocking(0)} を使ってソケットを非ブロッキングに
できます。C言語ではもっと複雑(１つを挙げると、BSD流儀の \code{O_NONBLOCK} と
と、それと殆ど見分けがつかないPosix流儀の \code{O_NDELAY} (\code{TCP_NODELAY}
とは全然違う)のどちらを使うか選ばなければなりません)ですが、考え方は同じです。
ソケットを作成した後、利用する前に、非ブロッキングの設定をします。
(実際には、あなたがバカ野郎でしたら、ブロッキングと非ブロッキングを切り替えて
使うこともできます)

大きな違いは、 \code{send}, \code{recv}, \code{connect}, \code{accept} が
何もせずに帰ってくることができるようになることです。
あなたには(もちろん)いくつかの選択肢があります。
戻り値とエラーコードをチェックして、自分の気を狂わすこともできます。
私の言うことが信じられないのなら、一度試してみてください。
あなたのアプリは大きく、バグだらけで遅いものになるでしょう。
なので、そんな頭のおかしい方法は無視して、正しい方法について話しましょう。

%Use \code{select}.
\code{select} を使ってください。

C言語では、\code{select}を使うのはかなり複雑です。
Pythonでは簡単です。でも、Pythonの \code{select} を理解したら、C言語を
使うときには殆どトラブルにあわないくらいには、C言語版に近いです。

\begin{verbatim}    ready_to_read, ready_to_write, in_error = \\
                   select.select(
                      potential_readers, 
                      potential_writers, 
                      potential_errs, 
                      timeout)
\end{verbatim}

\code{select} に３つのリストを渡します: 一つ目にはreadしたいソケットを
全部入れます; 二つ目には、writeしたいソケットを全部入れます; そして最後の
リストには、エラーチェックしたいものを入れます（普段は空のままです）。
１つのソケットが複数のリストに入ることがあることに注意してください。
\code{select} の呼び出しはブロッキングですが、タイムアウトを設定することが
できます。タイムアウトは慎重に設定してください - 何か事情があるので無い限り、
十分に長い時間（一分とか）を設定するのが良いです。


3つのリストが戻り値になります。それぞれのリストは read可能, write可能, 
エラー のソケットが入っています。各リストは引数に渡した対応するリストの
部分集合(空のこともある)になっています。そして、1つのソケットを引数の
複数のリストに含めていた場合、(最大でも)1つの出力リストにしか含まれません。


戻り値のread可能リストの中にソケットがあった場合、今までと少し違う点は、
そのソケットに対する \code{recv} が \emph{いくらか} を返すということです。
同じ事がwrite可能リストにも言えて、\emph{いくらか} を送ることができます。
送受信したかった全てでは無いかもしれませんが、\emph{いくらか} 送受信
できることは、全く送受信できないよりもマシです。(実際に、健康なソケット
がwrite可能として返されるのですが、それは単に出力側のネットワークバッファに
空きがあるということを意味しています。)

もし"サーバー"ソケットを持っているのであれば、それを potential_readers
リストに入れてください。read可能リストに入って出てきた場合、
\code{accept}が(ほぼ確実に)できます。
どこかに \code{connect} する新しいソケットを作ったら、それを
potential_writers リストに入れてください。ライト可能リストの中に
入って返されたら、接続された可能性が高いです。

\code{select}には1つ非常にやっかいな問題があります: 入力リストの
どこかに、やっかいな死に方をしたソケットが混ざっていると、
\code{select} が失敗します。そうすると、悪いソケットを見つけるまで、
リストの中のソケット一つ一つに対して \code{select([sock],[],[],0)} 
をしなければなりません。
タイムアウト時間が0なので長い時間はかかりませんが、これはとても
醜いです。

実際のところ、\code{select} はブロッキングソケットと共に使用しても
便利です。ブロックするかどうかを判定する1つの方法になります -
read可能として帰ってきたソケットにはバッファに何か入っています。
しかしながら、接続先が切れたのか単に他のことで忙しいだけなのかを
知る手がかりにはなりません。

\textbf{移植性に関する警告}: Unixでは、\code{select} はソケットと
ファイルの両方に対して動作します。これをWindowsで試してはいけません。
Windowsでは\code{select}はソケットに対してのみ動作します。
C言語においても、ソケットのより高度なオプションはWindowsでは別の
動作をすることに気をつけないといけません。
実際、Windowsでは私はよくソケットと共にスレッドを使用します(とても
上手く動作します)。
パフォーマンスを気にするのであれば、Windows用のコードとUnix用のコードが
全然別物にするしかないという現実を認めてください。(Macについて
どうしたら良いかは私は全然知りません)

%\subsection{Performance}
\subsection{パフォーマンス}

非ブロッキングソケットを使い、selectを使って多重化する方法がソケットを
利用する最速のコードであることは明白です。
CPUを使い切ることなく、LANの帯域を一杯に使って並列に通信できます。
1つの問題は、この方法で書かれたアプリはそれ以外のことはあまりできなく
なってしまうことです - いつでも受信を受け付けられる状態でいなければ
なりません。

あなたのアプリがそれ以外にも何かすると仮定すると、スレッドを使うことが
最適な答えになります(その場合も非ブロッキングソケットを使うと
ブロッキングソケットよりも高速です)。
不幸なことに、Unixの種類によってスレッドに関するAPIや品質はまちまちです。
なので、一般的なUnixでの解はforkして子プロセスで各コネクションを扱う
事です。このオーバーヘッドは重大です (特にWindowsでは、プロセス作成の
オーバーヘッドが莫大なので、この方法を使わないでください)。
また、この方法では、子プロセスが完全に独立しない限り、パイプ、共有メモリと
セマフォといった他のIPCを利用して親子のプロセス間通信をする必要があります。

最後に、ブロッキングソケットがいくらか非ブロッキングソケットよりも遅いとしても、
殆どの場合はそれが"正しい"方法だと言うことを覚えておいてください。
結局のところ、あなたのアプリがソケットから受信したデータを元に動作するのであれば、
わざわざロジックを複雑にする意味はなく、単に\code{recv}の代わりに\code{select}で
待つことができます。

\end{document}
