この記事では、次のことを検討します。
-TCPサーバーの作成。
-複数のクライアントをサーバーに並列に接続します。
-クライアントの無効化(ソケットの無効化)。
-データの送受信。
ソース: https : //github.com/valualit/QTcpServer01
QTcpServerまたは目的のポートをリッスンします
server_status変数にQTcpServerのステータスを保存し、サーバー操作中に過剰が発生しないようにします(0の場合、サーバーはポートをリッスンせず、1-リッスンします)。
この場合の信号は、ポートをリッスンする問題をもう一度解決します。 現在、newuser()スロットは、サーバーへの新しい接続が表示されたときにのみ呼び出されます。
tcpServer = new QTcpServer(this); connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newuser())); if (!tcpServer->listen(QHostAddress::Any, 33333) && server_status==0) { qDebug() << QObject::tr("Unable to start the server: %1.").arg(tcpServer->errorString()); } else { server_status=1; qDebug() << QString::fromUtf8(" !"); }
複数のクライアントをサーバーに並列接続する
以下のコードは、新しいソケットを作成し、シグナルをリッスンする方法を示しています。 また、ソケット記述子を取得します。これは、ソケットオブジェクトを保存するためのキーとして使用します。これは、今後の作業で役立ちます。
if(server_status==1){ qDebug() << QString::fromUtf8(" !"); QTcpSocket* clientSocket=tcpServer->nextPendingConnection(); int idusersocs=clientSocket->socketDescriptor(); SClients[idusersocs]=clientSocket; connect(SClients[idusersocs],SIGNAL(readyRead()),this, SLOT(slotReadClient())); }
QMap <int、QTcpSocket *> SClients; このマップは、作成されたソケットのオブジェクトを保存します。 たとえば、サーバーを強制的に停止し、開いているソケットを閉じる必要がある場合に使用します。 それらが閉じられていない場合、クライアントはサーバーからの応答を長時間待機し、接続を閉じません。 以下は、すべてのソケットを強制的に閉じるオプションです。
if(server_status==1){ foreach(int i,SClients.keys()){ QTextStream os(SClients[i]); os.setAutoDetectUnicode(true); os << QDateTime::currentDateTime().toString() << "\n"; SClients[i]->close(); SClients.remove(i); } tcpServer->close(); qDebug() << QString::fromUtf8(" !"); server_status=0; }
新しいソケットを作成するとき、おそらくreadyRead()シグナルに既に気づいているでしょう。クライアントがサーバーにデータを送信すると実行されます。この時点で、データを受信した後、クライアントに回答します。
// , QTcpSocket* clientSocket = (QTcpSocket*)sender(); // , , int idusersocs=clientSocket->socketDescriptor(); // QTextStream os(clientSocket); os.setAutoDetectUnicode(true); os << "HTTP/1.0 200 Ok\r\n" "Content-Type: text/html; charset=\"utf-8\"\r\n" "\r\n" "<h1>Nothing to see here</h1>\n" << QDateTime::currentDateTime().toString() << "\n"; // qDebug, // GET . qDebug() << clientSocket->readAll()+"\n\r"); // clientSocket->close(); // SClients.remove(idusersocs);
したがって、ポート33333でリッスンするサーバー(HTTPなど)を取得し、複数の要求を一度に処理して、目的の結果を得ることができます。
PS将来的には、ソケットを使用した大量のデータの転送について書きます。