イベントハンドリング
staticモードでの利用
TCP通信は、staticモードでも利用することができます。
受信データをコンソールに表示するように、先ほどのクライアントプログラムを以下のように書き換えてみましょう。
client2.pde
import processing.net.*;
Client myClient = new Client(this, "127.0.0.1", 5204);
while (myClient.active()) {
if (myClient.available() > 0) {
int dataIn = myClient.read();
println(dataIn);
}
}
println("disconnected");
先ほどと同じように、サーバープログラムからクライアントプログラムの順で実行しましょう。 コンソールに0から255の値が順に表示されていきます。 サーバープログラムを停止すると、コネクションが切断され、コンソールの最後に「disconnected」と表示されます。
※ 現在のProcessingのバージョンでは、不具合のため、全てのウィンドウの出力がアクティブなエディターのコンソールへ出力されます。
ここでは、whileループを使って、コネクションが確立されている間データの読み込みを続けます。
コネクションが確立されていることを確認するために active
メソッドを使用しています。
TCP通信を用いた基本的なプログラムでは、draw
関数のフレーム処理やwhileループを使ってデータの受信を待ち続けます。
しかし、このようなコネクションの制御はミスを起こしやすいです。
そこで、イベントハンドラでイベント処理を行うことで「データを受信した」というイベントが発生したときの処理だけを簡単に記述できるようになります。
TCPのイベント処理
Processingを用いたTCPプログラミングでは、serverEvent
と clientEvent
、 disconnectEvent
の3つのイベントハンドラが使用できます。
serverEvent
はコネクションが確立されたときに、clientEvent
はコネクションからデータを受信したときに、disconnectEvent
はコネクションが切断されたときに呼び出されます。
clientEvent
を用いてclient1.pdeを書き直してみると以下のようになります。
client3.pde
import processing.net.*;
Client myClient;
int dataIn;
void setup() {
size(200, 200);
myClient = new Client(this, "127.0.0.1", 5204);
}
void draw() {
background(dataIn);
}
void clientEvent(Client client) {
dataIn = client.read();
}
draw
関数では、現在の dataIn
の値に基づき背景を塗り潰し、clientEvent
関数では、サーバーから受信したデータを dataIn
に代入しています。
イベントハンドラを用いることで、描画処理と受信データの利用処理を分離することができ、プログラムの可読性が高まりました。
次に、server1.pde を以下のように修正し serverEvent
と disconnectEvent
を加えます。
server3.pde
import processing.net.*;
Server myServer;
int val = 0;
void setup() {
size(200, 200);
// Starts a myServer on port 5204
myServer = new Server(this, 5204);
}
void draw() {
val = (val + 1) % 255;
background(val);
myServer.write(val);
}
void serverEvent(Server s, Client c) {
println("connected");
}
void disconnectEvent(Client c) {
println("disconnected");
}
サーバープログラムを実行してから、クライアントプログラムを実行するとコンソールに「connected」と表示され、クライアントプログラムを停止すると「disconnected」と表示されます。