I have simple server with QTcpServer and simple client with QNetworkAccessManager.
When I request data from the server via curl or browser everything is ok
When I request data from any site via QNetworkAccessManager everything is ok
But I can not read data from QTcpServer via QNetworkAccessManager. All requests are reseted. QNetworkAccessManager (client) had send RST (reset connection) right after it received a data from server. And in client code we get the error: "Connection closed" (RemoteHostClosedError)
Aslo, I tried use QNetworkAccessManager from DownloadManager example and QTcpServer from FortuneServer example in various combinations, but the results were the same.
Tested Qt Versions:
Mac Qt 5.7
Linux Qt 5.7
Linux Qt 5.6.2
Linux Qt 5.5.1
Wireshark screenshot: qt-wireshark.png
The upper parts (with red lines) are results of QNetworkAccessManager, and the latest packets with success result are curl attempt to get data from QTcpServer
Also there is a simple example to reproduce the error: testNetwork.zip
And here is sample code for client:
void test(quint16 port)
{
QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest request;
request.setUrl(QUrl(QString("http://127.0.0.1:%1/").arg(port)));
manager->connect(manager, &QNetworkAccessManager::finished,
[](QNetworkReply *reply) {
qDebug() << QString("Finished. %1. %2").arg(reply->errorString()).arg(reply->error());
qDebug() << "readed: " << reply->readAll();
});
QNetworkReply *reply = manager->get(request);
reply->connect(reply, &QNetworkReply::readyRead, [reply]() {
qDebug() << QString("readyRead: '%1'").arg(QString(reply->readAll()));
});
}
and for server:
QTcpSocket socket;
...
if(socket.waitForReadyRead(5000))
{
QByteArray request;
request += socket.readAll();
QByteArray responce("HELLO, WORLD! HELLO, WORLD! HELLO, WORLD! HELLO, WORLD!");
socket.write(responce);
if(!socket.waitForBytesWritten())
{
qWarning() << QString("Error occurred in waitForBytesWritten() method of the tcp socket. %1 (%2)")
.arg(socket.errorString())
.arg(socket.error());
}
}
else
{
qWarning() << QString("Error occurred in read method of the tcp socket. %1 (%2)")
.arg(socket.errorString())
.arg(socket.error());
}
Also I created a Bug report on qt.io (QTBUG-56631)
Your client is making an HTTP request, but your server isn't an http server - it's not sending back a valid HTTP request.
Your client works when you point it at a web server, because that IS an http server.
QByteArray responce("HELLO, WORLD! HELLO, WORLD! HELLO, WORLD! HELLO, WORLD!");
isn't a valid HTTP response.
Related
I have a QTcpServer app and QTcpClient app.
See my screenshot.
When a client after interacting with server is disconnecting from server, on server side appears event (in client socket - in slot):
void CMyClient::onSocketDisplayError(QAbstractSocket::SocketError socketError)
{
QString sErr = m_pClientSocket->errorString();
m_pWin->AddMessageFormClient("Was gotten some error! " + sErr);
}
Error message:
The remote host closed the connection.
After that appears an event:
void CMyClient::onSocketDisconnected()
{
m_pWin->AddMessageFormClient("Client is disconnected!");
m_pWin->UpdateDisconnectUI();
}
Is it proper behavior on server side to generate onSocketDisplayError?
The code to disconnect on client side:
void MainWindow::on_pushButton_DisconnectFromServ_clicked()
{
m_pSocket->disconnectFromHost();
m_pSocket->waitForDisconnected(3000);
}
According with the documentation of QAbstractSocket, that is the class behind a QTcpSocket and thus your client and server (emphasis mine):
To close the socket, call disconnectFromHost(). QAbstractSocket enters QAbstractSocket::ClosingState. After all pending data has been written to the socket, QAbstractSocket actually closes the socket, enters QAbstractSocket::UnconnectedState, and emits disconnected(). If you want to abort a connection immediately, discarding all pending data, call abort() instead. If the remote host closes the connection, QAbstractSocket will emit error(QAbstractSocket::RemoteHostClosedError), during which the socket state will still be ConnectedState, and then the disconnected() signal will be emitted.
Therefore I'd say that:
disconnectFromHost is what you should use to close the client or the server
It's the proper behavior for the server to emit an error that indicates that a remote host closed the connection
I should send text messages to messaging platform like Slacks using incoming webhook. But my network as developing is different from public one, so I decided to use our company's proxy server which can connect to public one. Briefly,
Client - HTTP PROXY - SERVER (messaging platform)
1. Firstly, establish C-P connection using normal TCP socket.
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> m_socket;
boost::asio::ip::tcp::resolver resolver(m_io);
boost::asio::ip::tcp::resolver::query query("www.proxy.dev", "8080");
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::async_connect(m_socket.lowest_layer(), iterator,
boost::bind(&ClientSocket::HandleHandShake, this,
boost::asio::placeholders::error, shared_from_this()));
After connecting, send connection string to proxy.
m_stringStream << "CONNECT";
m_stringStream << " " << m_domain << ":443";
m_stringStream << " HTTP/1.1\r\n";
m_stringStream << "HOST: " << m_domain << ":443\r\n";
m_stringStream << "Proxy-Connection: keep-alive\r\n";
m_stringStream << "Connection: keep-alive\r\n";
2. Receive status code from proxy.
200 OK
3. Handshake
m_socket.set_verify_mode(boost::asio::ssl::verify_none);
m_socket.set_verify_callback([](auto&& preverified, auto&& ctx)
{
char subject_name[256];
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
return preverified;
});
m_socket.async_handshake(boost::asio::ssl::stream_base::client,
boost::bind(&ClientSocket::HandleHandShake, this,
boost::asio::placeholders::error, shared_from_this()));
4. Write HTTP POST, Read status code.
At 3 step, the error code informs me "short read" so i can't go next step.
I have searched many questions, but everything is not worked for me.
If I skip the handshake process, can receive "uninitialized" error.
If I also skip 'CONNECT' with proxy and send 'POST' directly to server, can receive "403 badrequest" error.
It's OK to connect server and send text message not through proxy server.
Thank you for reading.
I'm writing an Qt application and try to use Alexa API. I received access token, but I can't use API because of "Host not found" and "Connection closed".
My QNetworkAccessManager defined as
amazonHelper.data()->setNetworkAccessManager(view.data()->engine()->networkAccessManager());
...
void AmazonHelper::setNetworkAccessManager(QNetworkAccessManager *qnam) {
qDebug() << "setNetworkAccessManager()";
_manager = qnam;
connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
}
After executing
_manager->connectToHostEncrypted("https://avs-alexa-na.amazon.com");
I receive an error "Host not found".
After executing
QNetworkRequest request(QUrl("https://avs-alexa-na.amazon.com/v20160207/directives"));
request.setRawHeader("Authorization", "Bearer %1" + _accessToken.toUtf8());
_manager->get(request);
I receive an error "Connection closed".
What is a right way to use Amazon Alexa API?
Thanks in advance!
UPD1:
I found QNetworkRequest::SpdyAllowedAttribute in Qt documentation but when I tried to set this attribute I got the follow error: 'SpdyAllowedAttribute' is not a member of 'QNetworkRequest'
UPD2:
I tried to use libcurlcpp but after setting CURLOPT_HTTP_VERSION to CURL_HTTP_VERSION_2_0 got exception (https://github.com/JosephP91/curlcpp/issues/84)
I am working on a client-server project. On the client side, I have a few GUI windows containing different views (QTableView, QListView). I can send messages to the server just fine using the following method:
QByteArray bArray;
QDataStream out(&bArray, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);
//....//
out << quint16(0) << message;
out.device()->seek(0)
out.quint16(bArray.size() - sizeof(quint16));
socket.write(block);
My problem however comes on my server side. My server will receive the message, go through a couple of steps reading the message to decide the necessary info to get from the SQL database, run the Query returning a Model(QSqlTableModel, QSqlQueryModel), but should then send the respective model back to the client.
Is there any way for me to send this model back to the server?
I'm trying to implement an SSL server using the sample code from Qt documentation.
But after serverSocket->startServerEncryption(); is called, nothing happens - neither the encrypted() nor the sslErrors() signals are emitted (I've put breakpoints in the slots connected to them).
I test it by connecting an QSslSocket using connectToHostEncrypted to the port I'm listening on. The socket sends data, but my server does not respond (I'm using a TCP sniffer/proxy to see all the data being sent from client to server and from server to client).
This is my code for the server:
void SslServer::incomingConnection(int socketDescriptor)
{
qDebug() << "SslServer::incomingConnection()";
QSslSocket *serverSocket = new QSslSocket(this);
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
connect(serverSocket, SIGNAL(encrypted()), this, SLOT(ready()));
connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
serverSocket->startServerEncryption();
} else {
delete serverSocket;
}
}
And this is how I connect to it:
server = new SslServer(this);
server->listen(QHostAddress::Any, 3333);
QSslSocket *socket = new QSslSocket(this);
socket->connectToHostEncrypted("127.0.0.1", 3333);
According to the documentation:
Both the key and the local certificate are required if you are creating an SSL server socket.
And if you don't provide them, a "regular" error(QAbstractSocket::SocketError) signal is emitted by the socket. As you found out, the server doesn't send any data in that case.
SSH is not SSL. SSH client waits for initial data from server, while SSL client first sends data. So they both waiting for data from the other side.