大きなファイルを提供するQtでTCPサーバーを書いています。アプリケーション ロジックは次のとおりです。
- QTcpServer をサブクラス化し、incomingConnection(int) を再実装しました
- incomingConnection で、「Streamer」クラスのインスタンスを作成しています
- 「ストリーマー」は、incomingConnection の setSocketDescriptor で初期化された QTcpSocket を使用しています
- クライアントからのデータが到着したら、readyRead() スロット内から初期応答を送り返し、ソケットのシグナル bytesWritten(qint64) を Streamer のスロット bytesWritten() に接続します。
bytesWritten は次のようになります。
Streamer.h:
...
private:
QFile *m_file;
char m_readBuffer[64 * 1024];
QTcpSocket *m_socket;
...
Streamer.cpp
...
void Streamer::bytesWritten() {
if (m_socket->bytesToWrite() <= 0) {
const int bytesRead = m_file->read(m_readBuffer, 64 * 1024);
m_socket->write(m_readBuffer, bytesRead);
}
}
...
したがって、基本的に、保留中のデータがすべて完全に書き込まれたときにのみ、新しいデータを書き込んでいます。それが最も非同期的な方法だと思います。
そして、多くの同時クライアントがあるとかなり遅くなることを除いて、すべてが正しく機能します。
約5つのクライアントで-そのサーバーから約1 MB /秒の速度でダウンロードしています(自宅のインターネット接続の最大値)
約 140 クライアントの場合、ダウンロード速度は約 100 ~ 200 KB/秒です。
サーバーのインターネット接続は 10 Gbps で、140 クライアントで使用すると 100 Mbps 程度なので、問題はないと思います。
140 クライアントでのサーバーのメモリ使用量 - 2GB のうち 100 MB が利用可能
サーバーの CPU 使用率 - 最大 20%
ポート 800 を使用しています。
ポート 800 に 140 のクライアントがあり、ダウンロード速度が 100 ~ 200 KB/秒の場合、ポート 801 で別のコピーを実行し、問題なく 1 MB/秒でダウンロードしていました。
私の推測では、どういうわけか、Qt のイベント ディスパッチ (またはソケット通知機能) が遅すぎて、これらすべてのイベントを処理できないのです。
私はもう試した:
- Qt全体と私のアプリを-O3でコンパイルする
- libglib2.0-dev をインストールし、Qt を再コンパイルします (QCoreApplication は QEventDispatcherGlib または QEventDispatcherUNIX を使用するため、違いがあるかどうかを確認したかった)
- 特定のスレッドに現在どれだけのクライアントがいるかに応じて、streamer->moveToThread() を使用して、いくつかのスレッドを生成し、incomingConnection(int) で生成しますが、変更はありませんでした (ただし、速度ははるかにさまざまであることがわかりました)。
- を使用したワーカー プロセスの生成
コード:
main.cpp:
#include <sched.h>
int startWorker(void *argv) {
int argc = 1;
QCoreApplication a(argc, (char **)argv);
Worker worker;
worker.Start();
return a.exec();
}
in main():
...
long stack[16 * 1024];
clone(startWorker, (char *)stack + sizeof(stack) - 64, CLONE_FILES, (void *)argv);
次に、メイン プロセスで QLocalServer を開始し、incomingConnection(int socketDescriptor) から socketDescriptors をワーカー プロセスに渡します。正常に動作しましたが、ダウンロード速度は依然として遅かったです。
また試しました:
- incomingConnection() の fork()-ing プロセス - サーバーをほとんど殺した :)
- クライアントごとに個別のスレッドを作成 - 速度が 50 ~ 100 KB/秒に低下
- QRunnable で QThreadPool を使用 - 違いなし
私はQt 4.8.1を使用しています
私はアイデアを使い果たしました。
それはQt関連ですか、それともサーバー構成の何かですか?
それとも、別の言語/フレームワーク/サーバーを使用する必要がありますか? ファイルを提供する TCP サーバーが必要ですが、パケット間で特定のタスクを実行する必要もあるため、その部分を自分で実装する必要があります。