Qt によるネットワークプログラミング
Qt Network モジュールには、TCP/IP クライアントとサーバを記述するためのクラスが用意されています。QTcpSocket 、QTcpServer 、QUdpSocket のような低レベルのネットワーク概念を表すクラスや、QNetworkRequest 、QNetworkReply 、QNetworkAccessManager のような高レベルのクラスがあり、一般的なプロトコルを使ってネットワーク操作を行うことができます。
ネットワーク・プログラミングのためのQtのクラス
Qt Network C++ Classes ページに、Qt Network の C++ クラスのリストがあります。
HTTP の高レベルネットワーク操作
Network Access API は、一般的なネットワーク操作を実行するためのクラスを集めたものです。この API は、使用される特定の操作やプロトコル(例えば、HTTP 経由でのデータの取得や投稿)の抽象化レイヤーを提供し、一般的な概念や高レベルの概念に対応するクラス、関数、シグナルのみを公開します。
ネットワークリクエストはQNetworkRequest クラスで表現されます。 クラスはリクエストに関連する情報(ヘッダー情報や使用される暗号化など)の一般的なコンテナとしても動作します。リクエストオブジェクトが構築されるときに指定されるURLは、リクエストに 使用されるプロトコルを決定する。現在、アップロードとダウンロードには、HTTPとローカルファイルURL がサポートされている。
ネットワーク操作の調整は、QNetworkAccessManager クラスが行う。リクエストが作成されると、このクラスはそのリクエストをディスパッチし、進捗状況を報告するシグナルを発するために使われる。マネージャはまた、cookies を使ってクライアントにデータを保存したり、認証リクエストやプロキシの使用も調整する。
ネットワークリクエストへの応答はQNetworkReply クラスで表現される。これらはリクエストがディスパッチされるときにQNetworkAccessManager によって生成される。QNetworkReply によって提供されるシグナルを使用して、各リプライを個別に監視することもできますし、開発者はこの目的の代わりにマネージャのシグナルを使用し、リプライへの参照を破棄することもできます。QNetworkReply はQIODevice のサブクラスであるため、リプライは同期または非同期、つまりブロッキングまたはノンブロッキング操作として処理することができる。
各アプリケーションまたはライブラリは、QNetworkAccessManager のインスタンスを 1 つ以上作成して、ネットワーク通信を処理できます。
QTcpSocket および QTcpServer での TCP の使用
TCP(Transmission Control Protocol)は、HTTPやFTPを含むほとんどのインターネット・プロトコルがデータ転送に使用する低レベルのネットワーク・プロトコルです。TCPは、信頼性が高く、ストリーム指向で、コネクション指向のトランスポート・プロトコルです。特にデータの連続伝送に適している。
QTcpSocket クラスは、TCPのインタフェースを提供します。QTcpSocket 、POP3、SMTP、NNTPなどの標準ネットワーク・プロトコルや、カスタム・プロトコルを実装できます。
データ転送を開始する前に、リモート・ホストとポートに TCP 接続を確立する必要があります。接続が確立されると、相手のIPアドレスとポートが、QTcpSocket::peerAddress ()とQTcpSocket::peerPort ()を通じて利用できるようになります。ピアはいつでも接続を閉じることができ、データ転送は直ちに停止する。
QTcpSocket は非同期で動作し、 と同様に、ステータスの変化やエラーを報告するシグナルを発する。受信データの検出と送信データの自動フラッシュはイベントループに依存する。 () を使ってソケットにデータを書き込み、 () を使ってデータを読み込むことができる。 は2つの独立したデータストリームを表している。QNetworkAccessManager QTcpSocket::write QTcpSocket::read QTcpSocket
QTcpSocket はQIODevice を継承しているので、QTextStream やQDataStream と一緒に使用することができる。QTcpSocket から読み込む場合は、事前にQTcpSocket::bytesAvailable() を呼び出して、十分なデータが利用可能であることを確認する必要がある。
着信 TCP 接続を処理する必要がある場合(サーバー・アプリケーションなど)は、QTcpServer クラスを使用します。QTcpServer::listen() を呼び出してサーバーをセットアップし、QTcpServer::newConnection() シグナルに接続します。このシグナルは、クライアントが接続するたびに1回発信されます。スロットでは、QTcpServer::nextPendingConnection ()を呼び出して接続を受け付け、返されたQTcpSocket を使用してクライアントと通信します。
ほとんどの関数は非同期で動作しますが、QTcpSocket を同期(つまりブロッキング)で使用することも可能です。ブロッキング動作をさせるには、QTcpSocket のwaitFor...()関数を呼び出す。これらの関数は、シグナルが発せられるまで呼び出し元のスレッドを一時停止させる。例えば、ノンブロッキングのQTcpSocket::connectToHost ()関数を呼び出した後、QTcpSocket::waitForConnected ()を呼び出すと、connected ()シグナルが発せられるまでスレッドがブロックされる。
同期ソケットは、制御の流れがより単純なコードになることが多い。waitFor...()アプローチの主な欠点は、waitFor...()関数がブロックしている間、イベントが処理されないことである。GUIスレッドで使用した場合、アプリケーションのユーザー・インターフェースがフリーズする可能性があります。このため、非GUIスレッドでのみ同期ソケットを使用することを推奨します。同期的に使用する場合、QTcpSocket 、イベントループは必要ありません。
Fortune Clientと Fortune Serverの例では、QTcpSocket とQTcpServer を使用してTCPクライアント・サーバー・アプリケーションを記述する方法を示しています。イベントループを使用せずに)別のスレッドで同期QTcpSocket を使用する方法の例については「Blocking Fortune Client」を、アクティブなクライアントごとに1つのスレッドを持つマルチスレッドTCPサーバの例については「Threaded Fortune Server」も参照してください。
QUdpSocketでUDPを使用する
UDP(User Datagram Protocol)は、軽量で信頼性の低い、データグラム指向のコネクションレス・プロトコルです。信頼性が重要でない場合に使用できます。例えば、時刻を報告するサーバーはUDPを選ぶことができる。時刻のデータグラムが失われた場合、クライアントは単純に再リクエストを行うことができる。
QUdpSocket クラスは、UDPデータグラムの送受信を可能にする。このクラスはQAbstractSocket を継承しているので、QTcpSocket のインターフェースのほとんどを共有している。主な違いは、QUdpSocket が連続したデータストリームとしてではなく、データグラムとしてデータを転送することです。要するに、データグラムとは、転送されるデータに加えて、データグラムの送信者と受信者のIPアドレスとポートを含む、限られたサイズ(通常は512バイトより小さい)のデータパケットのことである。
QUdpSocket はIPv4ブロードキャストをサポートしています。ブロードキャストは、ネットワーク上のどのホストが最もハードディスクの空き容量が多いかを見つけるなど、ネットワーク発見プロトコルの実装によく使われる。あるホストがネットワークにデータグラムをブロードキャストし、それを他のすべてのホストが受信します。リクエストを受信した各ホストは、その時点のディスクの空き容量を返信として送信元に送り返す。送信元は、すべてのホストからの応答を受信するまで待ち、最も空き容量の多いサーバーを選んでデータを保存することができる。データグラムをブロードキャストするには、 (255.255.255.255)という特別なアドレスか、ローカルネットワークのブロードキャストアドレスに送信すればよい。QHostAddress::Broadcast
QUdpSocket::bind() は、TCPサーバーのQTcpServer::listen() と同じように、受信データグラムを受け入れるためのソケットを準備する。1つ以上のデータグラムが到着するたびに、QUdpSocket はreadyRead() シグナルを発する。QUdpSocket::readDatagram() を呼び出して、データグラムを読み込む。
ブロードキャスト・センダーと ブロードキャスト・レシーバーの例では、Qtを使用してUDPセンダーとUDPレシーバーを記述する方法を示します。
QUdpSocket また、マルチキャストもサポートしています。マルチキャストセンダーと マルチキャストレシーバーの例では、UDPマルチキャストクライアントの書き方を示しています。
QHostInfoを使ったホスト名の解決
ネットワーク接続を確立する前に、QTcpSocket 、QUdpSocket 、接続先のホスト名をIPアドレスに変換する名前検索を行います。この操作は通常、DNS (Domain Name Service) プロトコルを使用して実行されます。
QHostInfo は、このような検索を自分で実行できる静的関数を提供しています。ホスト名、 ポインタ、およびスロットのシグネチャを指定して () を呼び出すと、 が名前の検索を実行し、結果の準備ができたときに指定されたスロットを呼び出します。実際の検索は別のスレッドで行われ、名前検索を実行するオペレーティングシステム独自のメソッドを使用します。QObject QHostInfo::lookupHost QHostInfo
QHostInfo また、ホスト名を引数として受け取り、結果を返す () という静的関数も用意されている。この場合、名前検索は呼び出し元と同じスレッドで実行される。このオーバーロードは、非GUIアプリケーションや、GUIではない別のスレッドで名前検索を行う場合に便利です。(GUIスレッドでこの関数を呼び出すと、ルックアップの実行中に関数がブロックされる間、ユーザー・インターフェースがフリーズすることがあります)。QHostInfo::fromName
ネットワークプロキシーのサポート
Qt でのネットワーク通信は、ローカルとリモートの接続間でネットワークトラフィックを指示またはフィルタリングするプロキシを通して実行することができます。
個々のプロキシはQNetworkProxy クラスで表現され、プロキシへの接続の記述と設定に使用されます。異なるレベルのネットワーク通信で動作するプロキシがサポートされており、 SOCKS 5 のサポートは低レベルのネットワークトラフィックのプロキシを可能にし、 HTTP と FTP のプロキシはプロトコルレベルで動作します。詳しくはQNetworkProxy::ProxyType を参照。
プロキシは、ソケット単位でも、アプリケーション内のすべてのネットワーク通信でも有効にすることができる。新しくオープンされたソケットは、接続される前にQAbstractSocket::setProxy() 関数を呼び出すことで、プロキシを使用するようにできる。アプリケーション全体のプロキシは、QNetworkProxy::setApplicationProxy() 関数を使用することで、それ以降のすべてのソケット接続で有効にすることができる。
QNetworkProxyFactory は、特定のプロキシタイプに対するクエリに基づいてプロキシを提供する。QNetworkProxyQuery プロキシの目的 (TCP、UDP、TCPサーバー、URLリクエスト)、ローカルポート、リモートホストとポート、 使用プロトコル (HTTP、FTPなど) などの主要な条件に基づいてプロキシを選択することができる。
QNetworkProxyFactory::proxyForQuery() はファクトリに直接問い合わせるために使用されます。アプリケーション全体のプロキシポリシーは、QNetworkProxyFactory::setApplicationProxyFactory() にファクトリーを渡すことで実装できます。また、カスタムのプロキシポリシーは、QNetworkProxyFactory をサブクラス化することで作成できます。詳細は、クラスのドキュメントを参照してください。
©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。