In Qt environment, I have to initialize the socket
void CommSubFuel::initSubFuel()
{
// Initialize ZMQ context
context = zmq_ctx_new();
// Initializ`enter code here`e the subscriber
subscriber = zmq_socket(context, ZMQ_SUB);
qDebug() <<"initSubFuel->m_SubscriberFuel: " <<subscriber;
int rc = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, 0, 0);
if (rc) {
qDebug() << "Failed to initialize subscriber";
}
// Connect the subscriber
rc = zmq_connect(subscriber, (std::string("tcp://") + IP_SUBSCRIBER).c_str());
qDebug() << (std::string("tcp://").c_str()) << std::string(IP_SUBSCRIBER).c_str();
if (rc) {
qDebug() << "Failed to connect subscriber ";
}
}
and have a receive method. Communication is working as expected.
but I want to initialize the socket when I click button from mainwindow, and connect/disconnect to receive the data.
any suggestions. Thanks
Related
I want to make simple communication example on Qt Remote Objects. I want to make the communication peer-to-peer, therefore I'm trying to merge both Source and Replica of the same remote object functionality in one application (REPC_MERGED tool used to generate Source and Replica base classes).
#include <QtCore/QCoreApplication>
#include "MyPeerHost.h"
#include "Client.h"
#include <QDebug>
static QString peer_node_name(int number)
{
QString ret = QString("peer_%1").arg(number);
return ret;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyPeerHost peerHost; // just inherits auto-generated MyPeerSimpleSource
QUrl thisAddress = "local:" + peer_node_name(0);
QRemoteObjectHost sourceNode(thisAddress);
if(sourceNode.enableRemoting(&peerHost))
{
qInfo() << "Source remoting enabled successfully" << thisAddress;
QUrl remoteAddress = "local:" + peer_node_name(1);
QSharedPointer<MyPeerReplica> replica;
QRemoteObjectNode replicaNode;
if(replicaNode.connectToNode(remoteAddress))
{
qInfo() << "Replica connected to the address" << remoteAddress << "successfully";
replica.reset(replicaNode.acquire<MyPeerReplica>());
QString sourceClassName = peerHost.staticMetaObject.className();
qDebug() << "Replica wait for Source" << sourceClassName << "...";
if(replica->waitForSource(1000))
{
qInfo() << "Replica object completely initialized";
Client client;
client.setReplicaObject(replica);
client.sendMessage("AAA");
}
else
{
qCritical() << "Replica wait for Source" << sourceClassName << "FAILED" << replicaNode.lastError();
}
}
else
{
qCritical() << "Replica connect to the address" << remoteAddress << "FAILED" << replicaNode.lastError();
}
}
else
{
qCritical() << "Source remoting enable FAILED" << sourceNode.lastError();
}
return a.exec();
}
Application output:
Source remoting enabled successfully QUrl("local:peer_0")
Replica connected to the address QUrl("local:peer_1") successfully
Replica wait for Source "MyPeerHost" ...
Replica wait for Source "MyPeerHost" FAILED QRemoteObjectNode::NoError
As you see, replicaNode successfully connected to the non-existent node QUrl("local:peer_1").
What I am doing wrong?
You don't have valid Qt code.
Qt relies on an event loop to handle asynchronous behavior, which is started by the a.exec() at the end of your main() routine. Qt Remote Objects, in turn, relies on the event loop for all of its communication.
In your code, you create your objects on the stack, but in code blocks that go out of scope before you start the event loop. They will therefore be destructed before the event loop is kicked off.
I'd recommend starting with some of the examples, make sure they work, then grow what you are trying to do from there.
I'm new with Qt Creator and I'm trying to read data from a light sensor communicating by I2C. I made a class PortListener that should return data received on the console once called.
PortListener::PortListener(const QString &portName)
{
this->port = new QSerialPort();
port->setPortName(portName);
port->setBaudRate(QSerialPort::Baud9600);
port->setDataBits(QSerialPort::Data8);
port->setParity(QSerialPort::NoParity);
port->setStopBits(QSerialPort::OneStop);
port->setFlowControl(QSerialPort::NoFlowControl);
port->open(QIODevice::ReadWrite);
QByteArray readData = port->readAll();
qDebug() << "message:" << readData;
}
But the only message I have is:
QIODevice::read (QSerialPort): device not open
message: ""
I don't understand what that mean?
1.Open the serialport,then set the parameters.
PortListener::PortListener(const QString &portName)
{
this->port = new QSerialPort();
port->open(QIODevice::ReadWrite);
port->setPortName(portName);
port->setBaudRate(QSerialPort::Baud9600);
port->setDataBits(QSerialPort::Data8);
port->setParity(QSerialPort::NoParity);
port->setStopBits(QSerialPort::OneStop);
port->setFlowControl(QSerialPort::NoFlowControl);
}
2.Connect the readyRead signal to a slot, and the slot is like this.
void PortListener::readyReadSlot()
{
while (!port.atEnd()) {
QByteArray data = port.readAll();
}
}
This is much more like the QextSerialPort, the following is the code from my application.
void SpClient::start()
{
myComClient = new QextSerialPort(Setting::devCom);
if(myComClient->open(QIODevice::ReadWrite))
{
qDebug() << "open " << Setting::devCom << "as client success";
}
myComClient->setBaudRate(BAUD9600);
myComClient->setDataBits(DATA_8);
myComClient->setParity(PAR_NONE);
myComClient->setStopBits(STOP_1);
myComClient->setFlowControl(FLOW_OFF);
myComClient->setTimeout(50);
....
}
My guess is your code is failing to open the serial port, I have run into permissions issues under linux opening USB ports. You will just need to do a chmod to grant your $USER access mostly.
I use a QTcpServer that should listen alone on port. Language is c++ with Qt 5.9. The application must run under Win and Linux using MingW. The listen method from QTcpServer uses standard parameter for socket options. For Win10, Linux these options are set default to single usage of the listening port so listening works fine. Unfortunatly opposite to that Win7 offers shared usage which i must avoid.
I figured out that the QAbstractSocket class let me create a socket with the BindFlag::DontShareAddress. I can forward the socketdescriptor to the QTcpServer. Then the method listen fails (isn't listening) by stating: QTcpServer::listen() called when already listening. I check the ports status by using netstat.
My code sample is below:
bool TcpServer::init(QString ipAddress, quint16 port, Command::RoutingProperty clientSocketKind, QString interfaceName)
{
if (mServerIsInit == true) // only 1 server instance
{
return false;
mServer = new (std::nothrow) QTcpServer();
if (mServer == nullptr)
{
return false;
}
mClientSocketKind = clientSocketKind;
mInterfaceName = interfaceName;
// tries to set socket properties to a non sharing port
QTcpSocket tsocket;
if (!tsocket.bind(QHostAddress(ipAddress), port, QAbstractSocket::BindFlag::DontShareAddress))
{
qDebug() << "Socket bind fails";
}
else
{
qDebug() << "Socket bind success";
}
sd = tsocket.socketDescriptor(); // valid socket descriptor
if (!mServer->setSocketDescriptor(sd))
{
qDebug() << "SocketDescriptor fails";
}
sd = mServer->socketDescriptor();
qDebug() << "Socketdescriptor Server " << sd;
//end tries to set socket properties to a non sharing port
if (mServer->listen(QHostAddress(ipAddress), port)) // fails with message ... is always listening
// if (mServer->mServer->isListening()) // is not listening tells netstat
{
qDebug() << "Server status for listening ok: " << mServer->isListening();
qDebug() << "Server listen on " << mServer->serverAddress() << ":" << mServer->serverPort();
connect(mServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
connect(mServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(socketErr(QAbstractSocket::SocketError)));
mServerIsInit = true;
return true;
}
else
{
qDebug() << "Server status for listening fail" << mServer->isListening();
delete mServer;
mServer = nullptr;
return false;
}
}
Thanks for any idea how to set the socket options for a exclusive usage of the listening port.
Martin
As per the comment, you will probably need to call listen explicitly on the socket descriptor before calling QTcpServer::setSocketDescriptor.
The following code is untested but should give you some idea...
if (!tsocket.bind(QHostAddress(ipAddress), port, QAbstractSocket::BindFlag::DontShareAddress))
{
qDebug() << "Socket bind fails";
}
else
{
qDebug() << "Socket bind success";
}
sd = tsocket.socketDescriptor(); // valid socket descriptor
/*
* Now make an explicit call to `listen' so that the socket descriptor
* can be passed to QTcpSocket::setSocketDescriptoy.
*/
if (listen(sd, SOMAXCONN) == SOCKET_ERROR)
{
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(sd);
WSACleanup();
/*
* Handle error.
*/
}
if (!mServer->setSocketDescriptor(sd))
{
qDebug() << "SocketDescriptor fails";
}
As an aside, note that you need to be a bit more careful with error handling -- simply call qDebug and continuing will come back to bite you at some point.
I used QSerialPort to communicate with a serial port. But how to emit a signal when it is changed(connected or disconnected)?
OS is win7. Thanks.
I think I have a work-around for your problem (fixed mine at least).
I have a ComPort class that handles all my serial functionality of my GUI. When the user selected a COM-port, then a QTimer is started that checks the status periodically. When the timer is finished, the signal timeout() is emitted for which I wrote a custom slot:
// Custom slot to be called when timer times out.
void ComPort::checkComPortStatus()
{
QSerialPortInfo *info = new QSerialPortInfo;
QList<QSerialPortInfo> list = info->availablePorts();
bool port_still_available = false;
for (QSerialPortInfo &port : list) {
if (port.portName() == serial_port->portName())
port_still_available = true;
}
if (!port_still_available) {
qDebug() << "Selected COM-port," << serial_port->portName() << ", no longer available!";
delete serial_port;
serial_port = nullptr;
qDebug() << "COM-port is deleted.";
delete timer;
timer = new QTimer(this);
qDebug() << "COM-port timer is deleted.";
selectedPort_label->setText("Error: disconnected");
}
}
This, ofcourse, is only useful when the port is still closed. When the port is opened, a standard signal is emited by QT (please consult the documentation):
errorOccurred(QSerialPort::SerialPortError error)
I hope this helps!
Writing a chat using Qt. Got a problem. My client's QTcpSocket remains in connecting state, but the server emits newConnection() signal. Network session is not required. Why is that? Here is some code:
ChatClient::ChatClient(QObject *parent)
: QObject(parent) {
tcpSocket = new QTcpSocket(this);
QNetworkConfigurationManager manager;
if (QNetworkConfigurationManager::NetworkSessionRequired
& manager.capabilities()) {
qDebug() << "Network session required";
}
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(error(QAbstractSocket::SocketError)));
connect(tcpSocket, SIGNAL(connected()),
this, SLOT(requestForID()));
connect(tcpSocket, SIGNAL(readyRead()),
this, SLOT(receiveMessage()));
tcpSocket->connectToHost("192.168.0.100", PORT);
}
void ChatClient::requestForID() {
qDebug() << "Connected, requesting for ID";
QByteArray segment;
QDataStream out(&segment, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);
out << (quint16)0 << ID;
out.device()->seek(0);
out << (quint16)(segment.size() - sizeof(quint16));
tcpSocket->write(segment);
}
requestForID() is never being executed
ChatServer::ChatServer(QObject *parent)
: QObject(parent) {
tcpServer = new QTcpServer(this);
if (!tcpServer->listen(QHostAddress::Any, PORT)) {
qDebug() << "Unable to start the server"
<< tcpServer->errorString();
}
qDebug() << "Server port" << tcpServer->serverPort();
connect(tcpServer, SIGNAL(newConnection()),
this, SLOT(processConnection()));
}
void ChatServer::processConnection() {
qDebug() << "Incoming connection";
QTcpSocket *clientSocket = tcpServer->nextPendingConnection();
/*connect(clientSocket, SIGNAL(readyRead()),
this, SLOT(readData()));
readData(clientSocket);
connect(clientSocket, SIGNAL(disconnected()),
clientSocket, SLOT(deleteLater()));*/
QByteArray segment;
QDataStream out(&segment, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);
out << (quint16)0 << (quint16)Message
<< "Successfully connected";
out.device()->seek(0);
out << (quint16)(segment.size() - sizeof(quint16));
clientSocket->write(segment);
clientSocket->disconnectFromHost();
}
server displays incoming connection and the client does not emit connected remaining in connecting state, doesnt receive server message as well...
Any ideas?
I had the same problem and I found the reason and a solution.
connectToHost may not be called in the contstructor of the main window directly. Why?
The reason is, that the main message loop is not running yet at this time. Internally QAbstractSocketPrivate::fetchConnectionParameters() gets never called and Qt Socket Timeout Timer thinks connection is never established.
The solution is either to call it "delayed" like in
QMetaObject::invokeMethod(this, "OnDelayedConnect", Qt::QueuedConnection);
Or to call waitForConnected() after connectToHost