I am new at QT and I am trying to establish REST service (GET and POST) for my application. Meanwhile GET demand works fine, I can not execute POST demand (as result I got from server reply: Connection closed error). Do you have any suggestions what is wrong?
Constructor:
{
net_acc_manager = new QNetworkAccessManager(this);
connect(net_acc_manager, &QNetworkAccessManager::finished,this, &MyApp::httpFinished);
}
POST, response I get: Failed, error code #2. Server error explanation: Connection closed
void MyApp::Post_demand()
{
QUrl url = QUrl("http://192.168.2.1/od/6040/00");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QByteArray postdata="0000";
net_acc_manager->post(request,postdata);
qCDebug(log_hal) << Q_FUNC_INFO << "Request POST posted" << full_url.toString();
}
GET, that part works fine, output: Http post finished successfully.
void MyApp::Get_demand()
{
QUrl url = QUrl("http://192.168.2.1/od/6040/00");
reply=net_acc_manager->get(QNetworkRequest(QUrl("http://192.168.2.1/od/6040/00")));
qCDebug(log_hal) << Q_FUNC_INFO << "Request GET posted" << full_url.toString();
}
HttpFinished function
void MyApp::httpFinished(QNetworkReply *n_reply)
{
qCDebug(log_hal) << Q_FUNC_INFO << "Http request finished. Status code:" << n_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (n_reply->error()) {
qCCritical(log_hal) << Q_FUNC_INFO << "Status code:" << n_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qCCritical(log_hal) << Q_FUNC_INFO <<
QString("Failed, error code: #%1; Server error explanation: %2")
.arg(QString::number(n_reply->error())
, n_reply->errorString().replace(QRegExp("\%20"), " ")).toLatin1().data();
n_reply->deleteLater();
n_reply = Q_NULLPTR;
emit failed();
return;
}
qCDebug(log_hal) << QString("Http post finished successfully. Reply Text: %1\nElapsed time: %2 ms")
.arg(QString(n_reply->readAll()), QString::number(timer->elapsed())).toLatin1().data();
//dummy read, to clear buffer
n_reply->readAll();
n_reply->deleteLater();
n_reply = Q_NULLPTR;
emit finished();
}
after all, I have found the problem and solution. It appeared that the problem was at posting string at POST demand.
The line from POST function:
QByteArray postdata="0000";
Should actually be:
QByteArray postdata("\"0000\"");
Thanks anyway.
Related
I have added
ChromeOptions options = new ChromeOptions();
options.AddArgument("--ignore-certificate-errors-spki-list");
options.AddArgument("--ignore-ssl-errors");
options.AddArgument("test-type");
options.AddArguments("-incognito");
options.AddArgument("no-sandbox");
options.AddArgument("--start-maximized");
driver = new ChromeDriver(options);
But still getting:
ssl_client_socket_impl.cc(1061)] handshake failed error
How to suppress this error from console?
This error message...
[ERROR:ssl_client_socket_openssl.cc(855)] handshake failed; returned -1, SSL error code 1, net_error -2
...implies that the handshake failed between ChromeDriver and Chrome Browser failed at some point.
Root Cause
This error is generated due to net::SSLClientSocketImpl::DoHandshake and net::SSLClientSocketImpl implemented in ssl_client_socket_impl.cc
net::SSLClientSocketImpl::DoHandshake as follows:
int SSLClientSocketImpl::DoHandshake() {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
int rv = SSL_do_handshake(ssl_.get());
int net_error = OK;
if (rv <= 0) {
int ssl_error = SSL_get_error(ssl_.get(), rv);
if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) {
// The server supports channel ID. Stop to look one up before returning to
// the handshake.
next_handshake_state_ = STATE_CHANNEL_ID_LOOKUP;
return OK;
}
if (ssl_error == SSL_ERROR_WANT_X509_LOOKUP &&
!ssl_config_.send_client_cert) {
return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
}
if (ssl_error == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
DCHECK(ssl_config_.client_private_key);
DCHECK_NE(kSSLClientSocketNoPendingResult, signature_result_);
next_handshake_state_ = STATE_HANDSHAKE;
return ERR_IO_PENDING;
}
OpenSSLErrorInfo error_info;
net_error = MapLastOpenSSLError(ssl_error, err_tracer, &error_info);
if (net_error == ERR_IO_PENDING) {
// If not done, stay in this state
next_handshake_state_ = STATE_HANDSHAKE;
return ERR_IO_PENDING;
}
LOG(ERROR) << "handshake failed; returned " << rv << ", SSL error code "
<< ssl_error << ", net_error " << net_error;
net_log_.AddEvent(
NetLogEventType::SSL_HANDSHAKE_ERROR,
CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
}
next_handshake_state_ = STATE_HANDSHAKE_COMPLETE;
return net_error;
}
As per ERROR:ssl_client_socket_openssl.cc handshake failed the main issue is the failure of handshake when ChromeDriver handshakes with SSL pages in Chrome. Though Chromium team conducts test for SSL handshake through net_unittests, content_tests, and browser_tests but were not exhaustive. Some usecases are left out relying on the upstream tests.
Conclusion
This error won't interupt the execution of your Test Suite and you can ignore this issue for the time being till it is fixed by the Chromium Team.
You can restrict Chromium's log level to 3, so that only fatal errors are logged. Please bear in mind that you won't see any other error-related messages which might cause mayhem in production! The code looks like this:
var chromeOptions = new ChromeOptions();
chromeOptions.AddArgument("log-level=3");
var driver = new ChromeDriver(options : chromeOptions);
Chromium log levels are:
Description
Value
INFO
0
WARNING
1
LOG_ERROR
2
LOG_FATAL
3
Im having an issue connecting to QuestDB with libpqxx, i can establish a connection using the postgresql client as per the instructions here:
https://questdb.io/docs/guidePSQL
however, when i go to connect to QuestDB, using my simple program, that is more-or-less a slightly modified version of the standard "get me started" program:
https://github.com/jtv/libpqxx
#include <iostream>
#include <pqxx/pqxx>
int main(){
try
{
pqxx::connection C(
"user=admin "
"hostaddr=127.0.0.1 "
"password=quest "
"dbname=qdb"
"port=8812 ");
std::cout << "Connected to " << C.dbname() << std::endl;
pqxx::work W{C};
pqxx::result R{W.exec("SELECT name FROM employee")};
std::cout << "Found " << R.size() << "employees:\n";
for (auto row: R)
std::cout << row[0].c_str() << '\n';
std::cout << "Doubling all employees' salaries...\n";
W.exec0("UPDATE employee SET salary = salary*2");
std::cout << "Making changes definite: ";
W.commit();
std::cout << "OK.\n";
}
catch (std::exception const &e)
{
std::cerr << e.what() << '\n';
return 1;
}
return 0;
}
.. i get an error:
could not connect to server: Connection refused
Is the server running on host "127.0.0.1" and accepting
TCP/IP connections on port 5432?
what also complicates things possibly, is i cannot find anywhere pg_hba.conf ,are these even still a thing in version 10 of postgresql? i have /usr/lib/postgresql/10 but no config files.. and ive also searched the machine.. nothing found. any help would be much appreciated.
thankyou
The official documentation for libpqxx states that:
The connection string consists of attribute=value pairs separated by spaces, e.g. "user=john password=1x2y3z4". reference
Your connection string is:
pqxx::connection C(
"user=admin "
"hostaddr=127.0.0.1 "
"password=quest "
"dbname=qdb"
"port=8812 ");
You are missing a space after qdb, so the correct connection string is:
pqxx::connection C(
"user=admin "
"hostaddr=127.0.0.1 "
"password=quest "
"dbname=qdb "
"port=8812 ");
I just tried it and it works fine for me.
On a second hand, the following SQL statement:
W.exec0("UPDATE employee SET salary = salary*2");
Will not work, UPDATE is not supported yet by QuestDB. You can find more details about SQL support on the official documentation, here.
Once in 5 times, I get this "Bad file descriptor"error when I am attempting to shutdown or close the asio::ip::tcp::socket object. The following is the function to close the acceptor and socket.
void close_server()
{
acceptor_instance.close(error_code);
if (error_code)
{
std::cerr << "close_server(): acceptor::close()" << "Error: " << error_code.message() << std::endl;
}
if(socket_instance.is_open())
{
socket_instance.shutdown(asio::ip::tcp::socket::shutdown_both, error_code);
if (error_code)
{
std::cerr << "close_server(): socket::close()" << "Error: " << error_code.message() << std::endl;
}
socket_instance.close(error_code);
if (error_code)
{
std::cerr << "close_server(): socket::close()" << "Error: " << error_code.message() << std::endl;
}
}
else
{
std::cerr << "close_server(): socket_instance is already CLOSED" << std::endl;
}
}
Sometimes the socket_intance.is_open() fails. Attempting to call the socket.shutdown() or socket.close() without checking if the socket is open, gives "Bad file descriptor" error, that means the socket was already closed.
How to identify the cause?
How to know when it was closed?
I want to listen on a boost::asio::ip::tcp::socket with a timeout. For this, I am using the std::future::wait_for function. Below is my code:
std::optional<boost::asio::ip::tcp::socket> server::listen()
{
boost::asio::ip::tcp::socket sock(io_service);
std::future<void> accept_status = acceptor.async_accept(
sock, boost::asio::use_future);
if (accept_status.wait_for(std::chrono::seconds(10)) == std::future_status::timeout)
{
// I hope there's no race-condition between
// accepting a connection and calling cancel
acceptor.cancel();
std::cerr << "Timeout" << std::endl;
return {};
}
std::cerr << "Accepted a connection" << std::endl;
return {std::move(sock)};
}
This is not working though: the client is able to connect, but I still get a timeout. Which means that the future object and the asynchronous accept function aren't communicating. What am I missing?
I am using Boost version 1.65.
For Explorer_N, following is a complete program that does not work the way I expect:
#include <boost/asio.hpp>
#include <boost/asio/use_future.hpp>
#include <chrono>
#include <future>
#include <iostream>
#include <thread>
using namespace std;
void server_listen() {
boost::asio::io_service io_service;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 31132);
boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);
boost::asio::ip::tcp::socket socket(io_service);
std::future<void> accept_status = acceptor.async_accept(
socket, boost::asio::use_future);
while(true) {
if(accept_status.wait_for(std::chrono::seconds(10)) == std::future_status::timeout) {
acceptor.cancel();
std::cerr << "Timeout\n";
} else {
break;
}
}
// if I replace the lines starting from the async_accept call
// by just the following, everything works as expected
// acceptor.accept(socket);
std::cout << "Accepted a connection\n";
while(true) {
}
}
void client_connect() {
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::ip::tcp::endpoint endpoint(*resolver.resolve({"127.0.0.1", std::to_string(31132)}));
socket.connect(endpoint);
std::cout << "Connected to server\n";
while(true) {
}
}
int main() {
std::thread server(server_listen);
std::this_thread::sleep_for(std::chrono::seconds(2));
std::thread client(client_connect);
while(true) {
}
}
Compiled by g++ -std=c++17 <program>.cpp -lpthread -lboost_system -o <program>.
The output I get is:
Connected to server
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
...
To answer your claims:
"future object and the asynchronous accept function aren't communicating" -- not possible.
"the client is able to connect, but I still get a timeout.", -- your client connecting to a listener is one event and executing completion-handler (setting promise) is an another event.
So connection could've accepted at 9th second and callback would have scheduled to run at 11th second (for instance).
Remember, we are dealing with asynchronous ops, so making absolute prediction on future events is not something right I would say.
apart form that
// I hope there's no race-condition between
// accepting a connection and calling cancel
acceptor.cancel();
std::cerr << "Timeout" << std::endl;
return {};
acceptor.cancel(); just collect the pending waiters, and complete them with ec set to operation_aborted, if the handlers are already out to completion event queue, then cancel() is a no-op
Extending my answer based on OP's recent edit:
using namespace std;
void server_listen() {
boost::asio::io_service io_service;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 31132);
boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);
boost::asio::ip::tcp::socket socket(io_service);
auto work = make_work_guard(io_service);
using type= std::decay_t<decltype(work)>;
std::thread io([&](){io_service.run();});
std::future<void> accept_status = acceptor.async_accept(
socket, boost::asio::use_future);
if(accept_status.wait_for(std::chrono::seconds(10)) == std::future_status::timeout) {
acceptor.cancel();
std::cerr << "Timeout\n";
work.~type();
//break;
} else {
std::cout<<"future is ready\n";
work.~type();
// break;
}
io.join();
// if I replace the lines starting from the async_accept call
// by just the following, everything works as expected
// acceptor.accept(socket);
std::cout << "Accepted a connection\n";
}
void client_connect() {
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::ip::tcp::endpoint endpoint(*resolver.resolve({"127.0.0.1", std::to_string(31132)}));
socket.connect(endpoint);
std::cout << "Connected to server\n";
}
enter code here
int main() {
std::thread server(server_listen);
std::this_thread::sleep_for(std::chrono::seconds(2));
std::thread client(client_connect);
server.join(); client.join();
}
There are many things to take care of in your program (avoid unnecessary spin-loop, don't forgot to either join or detach the std::thread and make sure you call io_service::run when you use async* version)
Start
Connected to server
future is ready
Accepted a connection
0
Finish
I am developing a Qt client (C++) with gSOAP lib, which is supposed to discuss with a Web Service by Microsoft (WCF). I use SOAP 1.1 on both sides.
My client code is as follows :
CustomBinding_USCOREISynchronisation service;
soap_ssl_init(); /* init OpenSSL (just once) */
soap_init2(service.soap, SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE);
service.soap->max_keep_alive = 1000; // at most 100 calls per keep-alive session
service.soap->accept_timeout = 6000; // optional: let server time out after ten minutes of inactivity
if (soap_ssl_client_context(service.soap,
SOAP_SSL_NO_AUTHENTICATION,
NULL, /* keyfile: required only when client must authenticate to server (see SSL docs on how to obtain this file) */
NULL, /* password to read the key file (not used with GNUTLS) */
NULL, /* cacert file to store trusted certificates (needed to verify server) */ NULL, /* capath to directory with trusted certificates */
NULL /* if randfile!=NULL: use a file with random data to seed randomness */
))
{
soap_print_fault(service.soap, stderr);
exit(1);
}
_ns1__Connect req;
_ns1__ConnectResponse resp;
std::string strLogin = "tata#gmail.com";
std::string strPassword = "681982981298192891287B0A";
bool bInternalUser = true;
req.login = &strLogin;
req.password = &strPassword;
req.isInternalUser = &bInternalUser;
int err = service.__ns1__Connect(&req, &resp);
if (SOAP_OK == err)
qDebug() << ":D";
else
{
qDebug() << "Error : " << err;
soap_print_fault(service.soap, stderr);
}
qDebug() << "Result of Connect : " << resp.ConnectResult;
Problem: when I execute the program, I get a SIGPIPE (Broken pipe) in the "tcp_disconnect" function, on the exactly line "r = SSL_shutdown (soap-> ssl);".
Error message generated:
Error -1 fault: SOAP-ENV: Client [no subcode]
"End of file or no input: Operation interrupted or timed out"
Detail: [no detail]
Do you have any idea why? If you need more resources or information, please let me know!
A big thank in advance,
Louep.