Ние пишем проект, в който има клиент, който генерира xml заявки, изпраща ги до сървър, който анализира заявката и връща исканата информация в xml низ.
Приложението работи добре, когато xml отговорите са малки, но когато надхвърлят около 2500 знака, понякога се прекъсват от страна на клиента. Казвам понякога, защото когато клиентът и сървърът работят на една и съща машина и комуникират през домашния адрес 127.0.0.1, отговорите се анализират добре. Въпреки това, когато клиентът и сървърът са на различни машини и комуникират през lan, това е моментът, когато клиентът съкращава съобщението до около 2500 знака.
Комуникацията се осъществява чрез tcp сокети. Използваме Qt, клиентът има qTCPsocket, а сървърът qTCPserver и указател към qtcpsocket.
Смятаме, че възможно решение на нашия проблем е изпращането на xml на части, разделени по брой символи или по етикет. Въпреки че за нас е лесно да разделим съобщението на части, изпращането на частите и карането на клиента или сървъра да прочете и компилира частите в една 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 низ, разделен на части, и сървърът да прочете всички части и да го превърне отново в един низ?