• [soccerwindow2] Qtへ移行中.その11 (akiyama) 19:39:43

QUdpSocketにおいて,QIODevice::readyRead()が機能しなかった理由がようやく判明. QIODevice::readyRead()が有効になるのはソケットのbindが成功したときのみだが,soccerwindow2でソケットをbindするときにサーバ用のポート番号を指定してしまっていたために,bindが失敗していたからだった. サーバ用のポートをローカルにバインドしちゃってたら,そりゃ受信をキャッチなんかできないわな. すなわち,モニタクライアント用のソケットの初期化は,以下のように書かなければならない.

   QUdpSocket * socket = new QUdpSocket( this );
   // socket->bind( server_addr, server_port ); // Not OK
   socket->bind( 0 );  // OK
   if ( socket->socketDescriptor() == -1 )
   {
       return;
   }
   connect( socket, SIGNAL( readyRead() ),
               this, SLOT( handleReceive() ) );

自前のUDPSocketでは,この辺をラップしてしまって全く意識しなくて良いようになっていたから,逆に気づかなかった訳だ. UNIXネットワークプログラミングの復習をちゃんとやった方がいいかも. 感覚が鈍りすぎ.

これを調べるために,Qtのソースに直接デバッグメッセージを埋め込んだりしていたために,Qtのコンパイルを何回もやる羽目になってしまった. コンパイルするのに20〜30分かかるのは本当に参った. というわけで,非常につまらないミスで時間を食ってしまったが,何とか問題解決.

  • [soccerwindow2] QUdpSocketまとめ (akiyama) 21:40:12
  • rcssserverに対するクライアントとして初期化する場合は,bind(0)を使う.
  • デバッグサーバとして初期化する場合は,bind(ポート番号)
  • bindに成功すれば,ライブラリ側でQSocketNotifierが登録される.パケット受信のシグナルは QIODevide::readyRead()
  • パケットの送受信は,QUdpSocket::writeDatagram()/QUdpSocket::readDatagram()
    • writeDatagram()には送信先のアドレス情報とポート番号が必要.これらは,QUdpSocketとは別に保持しておかなければならない.
    • QAbstractSocket::connectToHost() を使えば,QIODevice::read()/QIODevice::write() によるメッセージ送受信が可能になり,送信時にアドレス情報とポート番号を指定する必要は無くなる.つまり,initコマンドが受け付けられてrcssserver側にクライアント用のソケットが出来れば,そのソケットとの接続をconnectToHost()で作り直せば良い?

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-03-14 (月) 14:51:37 (2024d)
SourceForge.JP
Creative Commons License
RoboCup tools by Hidehisa Akiyama is licensed under a Creative Commons 表示-非営利 2.1 日本 License.