So-net無料ブログ作成

大根日記 2015/12/29 [家庭菜園]

大根は暴落しているようですが、一応ぼちぼち収穫しています。

daikon2.png

正直、いまいちな出来です。
小さいし、一本当たりのコストを考えると買った方がましです。
でも子供が喜んで抜いているからまあいいか。


ソケットを使った複数クライアント間のプログラム構造について [Java]

プログラムの基本は入力されたデータを元に処理を行い、作成したデータの出力を行う。
基本はパンチカードの時代からあまり変わってないと思う。

ソケットを使って通信を行う場合も基本は同じだけれど、
大体のプログラムは複数の接続先と同時に通信を行う。

Javaを使って複数のソケットで同時に通信する場合、
プログラムの基本構造をどうすれば良いのか。
インターネットを検索してもなかなか良いページが見つからない。

ソケットを使用したプロセスのスレッド間でデータを受け渡すにはどうすれば良いのか?
受信したデータを List とか Vector(今時は使わない)に登録し、
読み出し側でポーリングするようなプログラムは
最初のデータを読み出すまでの待ち時間があって効率が悪いしカッコ悪い。


1.select() を使ってシングルタスクで複数の接続先と通信を行う。

この方法は C言語でプログラムを作っていた頃よくやっていた。
この頃はマルチCPUなんて殆ど無かったのでスレッドを使おうなんて考えもしなかった。

Xサーバがどうやって複数のXクライアントと通信を行い画面の描画を行っているのか。
その基本的な構造と同じだと思います。(今時のXサーバは分からないけどね。)

Java でも 1.4 から select() が使えるようになったので同じようなプログラムが記述できる。
逆に言うと 1.3 までは select() が使えなかったので
C言語で select() を使っていた私はには、
「何で Java に select() が無いんだ?」
と、ずっと思ってました。

このプログラム構造は大量の接続先があってもスレッド数が増えないのが利点。
でも基本的にシングルタスクなので、一つの入出力の処理に時間がかかると他の処理が止まってしまう。
通常は一つの入出力処理はあっという間に終わるので、一見同時に処理を行っているように見える。
一つの入出力処理が長い場合はデータ受信後そのデータの処理を別スレッドにするという手もある。

主となる一つのスレッドが複数のソケットと同時に接続しているので、接続先毎に別の処理が必要な場合、
select() から抜けてデータを処理する部分が複雑になる。
ソケットでは一回の受信で全てのデータを受信できる訳ではないので、
足りない分はもう一度受信する必要がある。送信も同じ。
接続先ごとにデータを管理するのが面倒。


2.接続先毎にスレッドを生成して通信を行う。wait()/notifyAll() 編

この方法は Java で select() が使えなかった 1.4 より前の頃に仕方なく行っていた方法。

スレッド間のデータの受け渡しには synchronize と LinkedList を使う。

ソケットからのデータ入力待ちには DataInputStream#read()、
あるいはバッファへの登録待ちにはThread#wait()を使う。

あるスレッドが受信したデータを他のスレッドが接続している接続先に送信したい場合、
目的の接続先に接続しているスレッドのLinkedListに送信データを登録し notifyAll()
を呼び出す。

wait() している全てのスレッドは自分の LinkedList にデータが登録されていればそのデータを読み出して
接続先のソケットにデータの送信を行う。

でも notifyAll() とか notify() は目的のスレッドを指定する事ができないので、別の言い方をすると、
「ポストにデータを入れたから各自ポストを確認してちょーだい!」
と言ってるのと同じで、なんか効率が悪い。


3.接続先毎にスレッドを生成して通信を行う。nio編

スレッド間の通信には synchronize LinkedList を使う。

データ入出力待ちには Selecter#select() を使う。

あるスレッドが受信したデータを他のスレッドが接続している接続先に送信したい場合、
目的の接続先に接続しているスレッドのLinkedListに送信データを登録し、
目的の接続先に接続しているスレッドの Selecter のwakeup()メソッドをを呼び出す。

select() で入出力待ちをしているスレッドは
自分の LinkedList にデータが登録されていればそのデータを読み出して
接続先のソケットにデータの送信を行う。

2.と違って目的のスレッドの待ち状態を解除する事ができる。
1.と違ってスレッドは接続先の処理に専念できるのでプログラムがわかりやすくなる。
接続数が多くなるとスレッド数が多くなる事を考えておく必要がある。

とりあえずこんな感じで、参考になるかな?

あんまり突っ込まないでね。思いつきで書いてるので。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。