私たちは、xml 要求を生成してサーバーに送信し、要求を解析して要求された情報を xml 文字列で返すクライアントが存在するプロジェクトを作成しています。
xml 応答が小さい場合、アプリケーションは正常に動作しますが、約 2500 文字を超えると、クライアント側で途切れることがあります。クライアントとサーバーが同じマシン上で実行され、ホーム アドレス 127.0.0.1 を介して通信する場合、応答が問題なく解析されるため、私は時々言います。ただし、クライアントとサーバーが異なるマシン上にあり、LAN を介して通信する場合、クライアントはメッセージを約 2500 文字にカットします。
通信は tcp ソケットによって行われます。Qt を使用しており、クライアントには qTCPsocket があり、サーバーには qTCPserver と qtcpsocket へのポインターがあります。
この問題の解決策として、xml を文字数またはタグごとに分割して送信することが考えられます。メッセージを部分に分割するのは簡単ですが、部分を送信し、クライアントまたはサーバーに部分を読み取らせて 1 つの xml 要求にコンパイルさせると、問題が発生します。
例として、クライアントがリクエストを複数の部分に分けて送信することをテストしたいと考えました。
以下は、リクエストを送信するためのクライアント関数呼び出しです。xmlReq は別の場所で生成され、渡されます。メッセージを部分に分割する例として、xml 要求から終了タグを取り除き、後で別の部分として送信します。
QString ClientConnection::sendRequest(QString xmlReq)
{
this->xmlRequest = xmlReq;
QHostAddress addr(address);
QList<QString> messagePieces;
xmlRequest.remove("</message>");
messagePieces.append(xmlRequest);
messagePieces.append("</message>");
client.connectToHost(addr,6789);
if(client.waitForConnected(30000))
{
for(int i = 0; i < messagePieces.length();i++)
{
client.write(messagePieces[i].toAscii(),messagePieces[i].length()+1);
qDebug() << "Wrote: " << messagePieces[i];
}
}
char message[30000] = {0};
xmlReply = "";
if(client.waitForReadyRead(30000)){
client.read(message,client.bytesAvailable());
}else{
xmlReply = "Server Timeout";
}
client.close();
xmlReply = (QString) message;
return xmlReply;
}
次はサーバーコードです。xml 終了メッセージ タグが表示されるまでクライアントからのメッセージを読み取り、データを処理して応答をクライアントに返すように記述されています。
サーバーを起動するコードです。
//Start the server, pass it the handler so it can perform queries
connect(&server, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
server.listen(QHostAddress::Any, 6789);
新しい接続を取得すると、次のようなacceptConnectionスロットを呼び出します
void CETServer::acceptConnection()
{
client = server.nextPendingConnection();
connect(client, SIGNAL(readyRead()), this, SLOT(startRead()));
}
startRead は次のようになります。
void CETServer::startRead()
{
char buffer[1024*30] = {0};
client->read(buffer, client->bytesAvailable());
QString readIn;
readIn = (QString) buffer;
ui->statusText->appendPlainText("Received: " + readIn);
//New messages in will be opened with the xml version tag
//if we receive said tag we need to clear our query
if (readIn.contains("<?xml version =\"1.0\"?>",Qt::CaseSensitive))
{
xmlQuery = "";
}
//add the line received to the query string
xmlQuery += readIn;
//if we have the clsoe message tag in our query it is tiem to do stuf with the query
if(xmlQuery.contains("</message>"))
{
//do stuff with query
ui->statusText->appendPlainText("Query received:" + xmlQuery);
QString reply = this->sqLite->queryDatabase(xmlQuery);
xmlQuery = "";
this->commandStatus(reply);
if(client->isWritable()){
//write to client
client->write(reply.toAscii(),reply.length()+1);
ui->statusText->appendPlainText("Sent to client: " + reply);
client->close();
}
}}
私の考えでは、開始読み取りは、クライアントがメッセージを書き込むたびに、サーバーがそれを読み取り、サーバーが保存する xmlRequest に添付するようにコーディングされています。メッセージに xml 終了タグが含まれている場合は、リクエストが処理されます。
ただし、クライアントが連続して書き込みを行った場合、サーバーは最初の書き込みのみを読み取り、すべてを読み取らず、xml 終了タグを受信しないため、要求を処理しません。
私が答える必要がある質問は、サーバーがクライアントの複数の書き込みに応答しないのはなぜですか? xml 文字列を分割して送信し、サーバーにすべての部分を読み取らせて、それを 1 つの文字列に再度変換できるようにするにはどうすればよいですか?