通信スレッドの構造が全然ダメでした…
最初の制御用通信の接続はするもののそこから全然進みません。
connected()のシグナルが届いた後最初のヘッダーを送出しますが、Brynhildrサーバさんから返事が届きません。
仕方がないので、サーバを起動しているVMware Workstation上のXP ProにWinsharkをインストールしました。
ネットワークパケットをキャプチャしてみます。XPでは少し古いバージョン(v1.10)を入れる必要があるそうです。
ポートとして55500を指定しているので、フィルタの所に"tcp.port==55500"を指定すれば、Brynhildr用のパケットがキャプチャできます。"Capture"メニューから"Start"を選んでキャプチャを開始します。
サーバへ接続してみますと…「ん、最初のコネクション確立用のパケットしか出ていない」みたいです。
接続を切断すると接続を切るための[FIN]パケットのやりとりしか出ていません。
ヘッダー(256バイト)を送出しているはずなんですが、それらしきパケットはありません。
Qtの質問サイトを探してみると少し気になる記述がありました。
QTcpSocketに write() した場合に flush() すると直ちにデータを送るよ、という指摘でした。
これまで特にflush() した記憶はないのですがうまく行っていたのでこれまで記述していませんでした。
早速write() の後に flush() するように記述して再実行しました。Winsharkの結果を見ると、
「お、256バイトのデータが送られている…」
flush() をしなければならないのか…、しかしシングルスレッドで今までうまく行っていたので納得がいきません。
確認のためQt Assistantを開き調べることにしました。QTcpSocketのスーパクラスであるQAbstractSocketのところに flush() の説明がありました。
「flush() すれば直ぐにwrite bufferをflushするよ、でも大体は必要なんだけどね…」 え?
「event loopで自動的に処理されるから…」 なんですと?
QThreadを継承しrun() の中に処理を記述すればいいよと入門書には書いてあったのですが、
その中でexec() を呼ばないとevent loopが開始されないのだそうです…うぇ…
で、そのイベントループでソケットのバッファがフラッシュされるのだそうです。
[参考]
http://www.qtcentre.org/archive/index.php/t-29932.html
run() の中で500msスリープしながら永久ループで構成していました。
単純にすると以下の様な構造です。
void run()
{
connectToServer();
while(true){
if (stopped)
break;
msleep(500);
}
disconnectToServer();
}
以下のような構造に変更しました。
void run()
{
connectToServer()
exec(); // event loop start
disconnectToServer()
}
QThread::exit()を呼び出せば、イベントループexec() は終了し、サーバーの切断処理を行い、スレッドが終了します。
というわけで、3つの通信スレッドを起動して、Brynhildrサーバーさんと通信し、データが転送できるところまで確認できたのですが…
« Andoroidへの道 | トップページ | 「ブリュンヒルデ零式」の公開、だそうです »
コメント