Qtでソケット通信を試してみた(UDP)
能書き
今回はQtのQUdpSocketを用いたUDPのソケット通信を試してみた。
ネットワーク通信については詳述できないしないが、次のページが参考になる。
また、QtのGUIの使い方は、以下のページで紹介したとおり。環境も同様。
ただし、モジュールの『Network』を有効にすること。
サンプルコードの挙動
Senderのエディットに文字列を入れてボタンを押すと、Recieverに反映される。
ただし、それぞれ別のアプリケーションとして起動する。それだけ。
このコードを実行するとき、このような警告が出ることがある。
両方のチェックボックスにチェックを入れて、アクセスを許可すること。
サンプルコード―送信側
clicked()シグナルと、ダイアログのsendDatagram()スロットを連結する。
まずヘッダファイル。
先のスロットと並んで、ソケットとポート番号を宣言している。
ポート番号は、ウェルノウン*1でなければ、適当に選んで大丈夫(だと思う)。
ポート番号に関する解説は、このページが詳しい。
次に、ソースファイル。
23行目のwriteDatagram()の第二引数には、通信先のIPアドレスを指定する。
- QHostAddress::LocalHost
自分自身と通信する、ループバックアドレス。実験段階で特に有用だろう。 - QHostAddress::Broadcast
同一ネットワーク上の全てのノードに送信するアドレス。ただし、ブロックするルータもある。 - QHostAddress::QHostAddress( "xxx.xxx.xxx.xxx" )
コンストラクタを用いて、IPv4アドレスを指定する方法。
18-21行目は、送信用のバイト列をうまく扱うための方便。
とりあえずは盲目に真似して、C++のストリームの恩恵に預かってよいだろう。
このように、送信側はただ『データを成形して』『送信する』だけで実装できる。
サンプルコード―受信側
受信側のウィジェットは単純で、ラベルが一つだけあるダイアログだ。
コードは次のとおり。
ヘッダファイルは送信側と酷似している。
ソースファイルに関しても、結局は『受信して』『データを解析して』いるだけ。
21行目から24行目は、このままでいろいろなニーズに使いまわせる。
受信側特有の処理は二つある。第一は、cppファイル9行目のbind()だ。
どのデータを受け取るか選ぶために、前もってポート番号を知らせる必要がある。
第二の特有の処理は、readyRead()シグナルと処理スロットを接続することだ。
サンプルコード10,11行目の処理にあたる。
readyRead()シグナルは、送信されたデータを読む準備が出来ると発呼される。
まとめ
- QUdpSocketクラスは、低信頼/高速の通信プロトコルを提供する。
- 送信側/受信側が、共通のポート番号を知っておく必要がある。
- 送受信にはQByteArrayクラスのバイト列を用いる。
QDataStreamクラスを利用すると便利。 - 受信側は、前もってbind処理を行っておくこと。
- データが受信されると、readyRead()シグナルが発呼される。
案外単純である。
ストリームの取扱いに関しても、そのうち書く...かもしれない。
書かないかもしれない。
ただし
ただし、このコードでは、短時間に連続して送られるデータには対応できない。
処理に手間取っているうちに送信されたデータは無視される。
全てのデータを扱う必要があるのなら、
hasPendingDatagrams()を用いたループ内に処理命令を書くこと。
リファレンスのサンプルコード片が参考になる。
これについてはそのうち書く。
*1:0~1023 予約されているポート