将qt客户端连接到嵌入式jetty服务器时遇到一些问题。
首先,我使用以下组件:
Qt 4.4.3(使用主动openssl支持编译) 码头8.8.1 java 6
我知道,这些版本不是最新版本,但由于许可问题和客户意愿,我无法使用新版本。
因此,情况是qt客户端必须向jetty服务器发送http GET和POST请求。只要我在QHttp对象上使用简单的http就可以正常工作,当我切换到SSL时就会出现问题。
我的第一次尝试是将QSslSocket对象用于GET请求:
// Load certs + private key to socket
_pSocket = new QSslSocket(this);
_pSocket->setLocalCertificate(_certificate);
_pSocket->setPrivateKey(_privatekey);
_pSocket->addDefaultCaCertificate(_cacertificate);
connect (_pSocket, SIGNAL(encrypted()), this, SLOT(_encrypted()));
_pSocket->connectToHostEncrypted("localhost", 8000);
具有加密状态的以下插槽功能:
void TestClient::_encrypted() {
QString _path("/testpath/list");
QByteArray buffer("GET ");
buffer.append(_path).append(" HTTP/1.1\r\n");
_pSocket->write(buffer);
}
我有第一个问题:
这导致以下字符串,据我所知,符合RFC 2616:
"GET /testpath/list HTTP/1.1\r\n"
由于某种原因,jetty服务器存在问题,保持循环直到客户端因超时而关闭连接。
但如果我使用以下字符串,它就完美无缺:
"GET /testpath/list\r\n"
这是我的第一个问题:你现在对这种行为有解释吗?我可以忍受它,但我想知道原因
我的第二个问题是POST请求,这总是失败。
我已经尝试过这些例子:
"POST /testpath/receive/\r\n{"data":"hello world ?!"}\r\n"
"POST /testpath/receive/ HTTP/1.1\r\n{"data":"hello world ?!"}\r\n"
"POST /testpath/receive/\r\n\r\n{"data":"hello world ?!"}\r\n"
"POST /testpath/receive/ HTTP/1.1\r\n\r\n{"data":"hello world ?!"}\r\n"
我感觉身体每次都是空的,所以我的服务器崩溃了,因为他试图将一个空字符串解析为json。 至少,以下日志显示:
2013-11-19 17:11:51.671, INFO, foo.bar.RepositoryHandler, qtp11155366-16 - /testpath/receive request type : /receive
2013-11-19 17:11:51.811, ERROR, foo.bar.RepositoryHandler, qtp11155366-16 - /testpath/receive missing or unknown elements in JSON request. Check JSON against documentation
2013-11-19 17:11:51.874, WARN, org.eclipse.jetty.server.AbstractHttpConnection, qtp11155366-16 - /testpath/receive /testpath/receive
java.lang.NullPointerException: null
at foo.bar.RepositoryHandler.decodeViewingRequest(RepositoryHandler.java:366) ~[MyServer.jar:na]
at foo.bar.RepositoryHandler.handle(RepositoryHandler.java:182) ~[MyServer.jar:na]
所以,总之,我认为我的请求中有几个主要错误。但是哪个?
我的第二次尝试是使用QHttp对象并将其使用的QSocket更改为我已启动的QSslSocket。
这是主要功能的代码:
QSslSocket* _pSocket;
QHttp* _pHttp;
int _id;
QBuffer* _pBuffer;
QByteArray _data;
_pSocket = new QSslSocket(this);
_pSocket->setLocalCertificate(_certificate);
_pSocket->setPrivateKey(_privatekey);
_pSocket->addDefaultCaCertificate(_cacertificate);
QUrl url;
url.setScheme("https");
url.setHost("localhost");
url.setPort(8001);
url.setPath("/testpath/receive");
connect (_pSocket, SIGNAL(encrypted()), this, SLOT(_encrypted()));
connect(_pHttp,SIGNAL(requestFinished(int,bool)),this,SLOT(_requestFinished(int,bool)));
connect(_pHttp,SIGNAL(done(bool)),this,SLOT(_done(bool)));
_pBuffer = new QBuffer(&_data);
_pHttp->setSocket(_pSocket);
_pSocket->connectToHostEncrypted(strHost, strPort.toInt());
_id = _pHttp->get(url.toString(),_pBuffer);
回调:
void _requestFinished(int id, bool error) {
if(id = _id)
qDebug() << "data=" << _data;
}
void _encrypted() {
qDebug() << "encrypted";
}
void _done(bool error) {
logInfo() << "_done";
if(_pHttp) {
_pHttp->abort();
delete _pHttp;
_pHttp = 0;
}
if(_pBuffer) {
delete _pBuffer;
_pBuffer = 0;
}
if(_pSocket) {
_pSocket->disconnectFromHost();
delete _pSocket;
_pSocket = 0;
}
}
我想,我只需要改变_pHttp-&gt; get调用的位置,也许是在_encrypted回调中,但我不确定。
一些好的建议?
谢谢, 罗伯特
答案 0 :(得分:0)
根据RFC2616,您的HTTP请求不完整。
"GET /testpath/list HTTP/1.1\r\n"
这是无效的。
试试这个。
"GET /testpath/list HTTP/1.1\r\n" + /* request line (required) */
"Host: localhost\r\n" + /* host header (required minimum) */
"\r\n" /* terminating CR + LF (required) */
中所述
The most common form of Request-URI is that used to identify a
resource on an origin server or gateway. In this case the absolute
path of the URI MUST be transmitted (see section 3.2.1, abs_path) as
the Request-URI, and the network location of the URI (authority) MUST
be transmitted in a Host header field. For example, a client wishing
to retrieve the resource above directly from the origin server would
create a TCP connection to port 80 of the host "www.w3.org" and send
the lines:
GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.w3.org
Request-URI行和主机标题标题是强制性的。