2013-11-22 2 views
0

qt 클라이언트를 임베디드 부두 서버에 연결하는 데 문제가 있습니다.SSL로 Qt를 부두 서버에 연결

는 처음에 나는 다음과 같은 구성 요소를 사용

Qt는 4.4.3 (활성 OpenSSL을 지원하도록 컴파일) 부두 8.8.1 자바 내가 아는 6

를, 버전은 가장 최근 없습니다 라이센싱 이슈와 고객의 소원 때문에 더 새로운 것을 사용할 수는 없습니다.

그래서 시나리오는 qt 클라이언트가 http GET 및 POST 요청을 부두 서버로 보내야한다는 것입니다. QHttp 객체로 간단한 http를 사용하면 SSL로 전환 할 때 문제가 발생합니다.

// 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); 
} 

는 내가 처음으로 문제가 :

내 첫 번째 시도는 GET 요청에 대한 QSslSocket 객체를 사용하는 것이 었습니다

다음 문자열은 RFC 2616을 준수하는 것으로 나타납니다.

"GET /testpath/list HTTP/1.1\r\n" 

어떤 이유로 인해 갑판 서버에는 시간 초과로 인해 클라이언트가 연결을 닫을 때까지 루프가 유지되는 문제가 있습니다.

하지만 다음 문자열을 사용하는 경우, 그것은 완벽하게 작동합니다

여기
"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 개체를 사용하고 이미 시작한 QSslSocket에서 사용하는 QSocket을 변경하는 것입니다. 난 단지 아마도에서 얻을>는 _pHttp-의 위치를 ​​변경 호출해야,

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; 
    } 
} 

내가 생각 :

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); 

그리고 콜백 : 여기

는 메인 함수의 코드입니다 _ 암호화 된 콜백이지만 확실하지 않습니다.

좋은 조언이 있습니까?

감사합니다, 로버트

답변

0

귀하의 HTTP 요청이 RFC2616 당, 불완전하다.

"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) */ 

Section 5.1.2

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 

요청-URI 라인 호스트 헤더 헤더에 명시된이 의무화되어있다.

+0

POST 요청 본문이 항상 비어있는 이유는 그 때문입니다. – Zostran

+0

'POST '요청의 경우'Content-Length' 헤더도 포함시켜야합니다. –

+0

'GET'과'POST' 요청 모두에'Connection : close' 헤더를 포함시키는 것도 도움이 될 것입니다. (서버가 응답 후에 열린 커넥션을 닫는 것을 알고 있음). –