xml 요청을 생성하고 요청을 구문 분석하고 요청 된 정보를 xml 문자열로 반환하는 서버로 클라이언트를 보내는 클라이언트가있는 프로젝트를 작성합니다.Qt를 사용하여 TCP 소켓을 통해 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;
}
다음은 Google 서버 코드입니다. XML 닫는 메시지 태그를 볼 때까지 클라이언트에서 메시지를 읽은 다음 데이터를 처리하고 클라이언트에게 응답을 다시 보냅니다.
서버를 시작하는 코드입니다. 그것은이
void CETServer::acceptConnection()
{
client = server.nextPendingConnection();
connect(client, SIGNAL(readyRead()), this, SLOT(startRead()));
}
처럼 보이는 acceptConnection 슬롯을 호출하는 새로운 연결을 얻을 때
//Start the server, pass it the handler so it can perform queries
connect(&server, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
server.listen(QHostAddress::Any, 6789);
은 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 문자열을 보내서 조각으로 나누어서 서버가 모든 조각을 읽고 다시 한 문자열로 바꿀 수 있도록 만드는 방법에 대해 어떻게해야합니까?
이것은 보안 구멍입니다. "char 버퍼 [1024 * 30] = {0}; 클라이언트 -> 읽기 (버퍼, 클라이언트 -> bytesAvailable());" 버퍼에 피팅하는 것보다 더 많은 바이트가있을 수 있으며 버퍼 오버 플로우가 발생합니다. –