使用SSL将Qt连接到jetty服务器

使用SSL将Qt连接到jetty服务器,qt,ssl,jetty,embedded-jetty,Qt,Ssl,Jetty,Embedded Jetty,我在将qt客户端连接到嵌入式jetty服务器时遇到一些问题 首先,我使用以下组件: Qt 4.4.3(使用活动openssl支持编译) 码头8.8.1 爪哇6 我知道,这些版本不是最新的,但由于许可问题和客户的愿望,我不能使用更新的版本 因此,场景是qt客户端必须向jetty服务器发送http GET和POST请求。只要我对QHttp对象使用简单的http,它就可以正常工作,当我切换到SSL时问题就开始了 我的第一次尝试是对GET请求使用QSslSocket对象: // Load certs +

我在将qt客户端连接到嵌入式jetty服务器时遇到一些问题

首先,我使用以下组件:

Qt 4.4.3(使用活动openssl支持编译) 码头8.8.1 爪哇6

我知道,这些版本不是最新的,但由于许可问题和客户的愿望,我不能使用更新的版本

因此,场景是qt客户端必须向jetty服务器发送http GET和POST请求。只要我对QHttp对象使用简单的http,它就可以正常工作,当我切换到SSL时问题就开始了

我的第一次尝试是对GET请求使用QSslSocket对象:

// 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对象,并将它使用的QSSocket与我已经启动的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;
    }
}
void\u请求已完成(int-id,bool错误){
if(id=_id)

qDebug()根据,您的HTTP请求不完整

这是无效的

试试这个

"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) */
如中所述

最常见的请求URI形式是用于标识
源服务器或网关上的资源。在本例中,绝对
URI的路径必须按如下方式传输(见第3.2.1节,abs_路径)
请求URI和URI(授权)的网络位置必须是
将在主机头字段中传输。例如,客户端
直接从源服务器检索上面的资源
创建到主机“www.w3.org”端口80的TCP连接并发送
台词:
GET/pub/WWW/TheProject.html HTTP/1.1
主持人:www.w3.org

请求URI行和主机标头是强制的。

谢谢,这就是为什么POST请求正文总是空的原因。对于
POST
请求,还应该包含
Content Length
标头。在
GET
上都包含
连接:close
标头也会有所帮助e> POST
请求(这样服务器知道在响应后关闭打开的连接)。
"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) */