QLocalSocket doesn't send anything - c++

well, i'm still trying to get a IPC running through a QLocalSocket.
Obviously my socket connects, the connection gets accepted, but when i try to send something
void ServiceConnector::send_MessageToServer(QString message) {
if(!connected){
m_socket->connectToServer(m_serverName);
m_socket->waitForConnected();
}
char str[] = {"hallo welt\0"};
int c = m_socket->write(str,strlen(str));
qDebug() << "written: " << c;
}
i get no response...the server's socket does just nothing.
server's read implementation:
void ClientHandler::socket_new_connection() {
logToFile("incoming connection");
clientConnection = m_server->nextPendingConnection();
socket_StateChanged(clientConnection->state());
auto conn = connect(clientConnection, SIGNAL(disconnected()),this, SLOT(socket_disconnected()));
conn = connect(clientConnection, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)),this,SLOT(socket_StateChanged(QLocalSocket::LocalSocketState)));
conn = connect(clientConnection, SIGNAL(readyRead()), this, SLOT(socket_readReady()));
clientConnection->waitForReadyRead();
socket_readReady();
}
void ClientHandler::socket_readReady(){
logToFile("socket is ready to be read");
logToFile((clientConnection->isOpen())? "open: true":"open: false");
logToFile((clientConnection->isReadable())? "readable: true":"readable: false");
QDataStream in(clientConnection);
in.setVersion(QDataStream::Qt_4_0);
if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) {
return;
}
QString message;
in >> message;
logToFile("Message recieved" + message);
send(message);
emit messageReceived(message);
}
outputs:
client:
[Debug]: ConnectingState
[Debug]: ConnectedState
[Debug]: socket_connected
[Debug]: written: 10
server:
[Debug]: incoming connection
[Debug]: socket is ready to be read
[Debug]: open: true
[Debug]: readable: true
the socket's readReady() signal is never emitted, so i decided to use
clientConnection->waitForReadyRead();
socket_readReady();
...but obviously that doesn't work either. waitForReadyRead is fired immediately after the write function of the client, which i think means that it is now ready to read...
[edit] the auto conn = connection(...) was for debugging, to check if they connect properly....they do

Note: you should really check the return value of waitForConnected(). There's no point in proceeding further if the client doesn't manage to connect to the server.
But I think your actual issue is that you're writing a simple 8-bit string like "hallo welt\0" but you're reading with QDataStream which expects a binary format (for QString, that means unicode, and length first), this doesn't match.

Related

How to read complete data using QTcpSocket (Qt4.7)

I created a TcpServer in order to receive data from a client. The client sends a lot of messages and I would like to read them. So far my TcpServer.cpp looks like this :
void TcpServer::serverStart()
{
server = new QTcpServer(this);
if (!server->listen(QHostAddress("192.168.x.x"), 48583))
{
qDebug() << "Not listening";
server->close();
delete server;
return;
}
else {
qDebug() << "Listening";
}
connect(server, SIGNAL(newConnection()), this, SLOT(newConnection()));
}
void TcpServer::newConnection()
{
socket = server->nextPendingConnection();
qDebug() << "Client connected";
connect(socket, SIGNAL(readyRead()), this, SLOT(getData()));
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
}
void TcpServer::getData()
{
QByteArray buffer;
while (socket->bytesAvailable())
{
buffer.append(socket->readAll());
}
qDebug() << buffer;
}
void TcpServer::serverStop()
{
server->close();
delete server;
}
I know my getData function needs a lot more in order to receive everything but I don't understand the steps needed to do that.If someone could give me some pointers I would be grateful !
TCP is a transport protocol which is stream oriented. Imagine it as being a continuous flow of data. There are no messages defined by TCP yet, because once again it is a continuous flow of data.
I'm taking from your comment that you are not using any application layer protocol. You need an application layer protocol, like e.g. http, which is then defining "messages" and giving you further instructions on how to read a complete message.

UDP Packet can be seen on wireshark, not seen from output of code

I am trying to receive packet from UDP-connected infrared camera. (FLIR Lepton 2.5) And I'm trying to run my codes on Windows 10, Qt Creator 4.5, Qt 5.9.
As you can see on the capture below, my UDP-connected infrared camera sends UDP packets.
And here's my code:
// myudp.cpp
#include "myudp.h"
#include <QNetworkProxy>
MyUDP::MyUDP(QObject *parent) :
QObject(parent)
{
// create a QUDP socket
socket = new QUdpSocket(this);
socket_cam = new QUdpSocket(this);
cam_address = QHostAddress("192.168.10.197");
cam_port = 32197;
connect(socket, SIGNAL(connected()), this, SLOT(readNwrite()));
socket->connectToHost(cam_address, cam_port, QIODevice::ReadWrite);
if (socket->waitForConnected(2000))
qDebug("Connected!");
else
qDebug("Cannot be connected..");
qDebug() << socket->state();
// seems to be connected...
}
void MyUDP::readNwrite()
{
QByteArray data;
qint64 resize_size = socket->pendingDatagramSize();
//socket have NO size(resize_size == -1, ERROR!)
if(resize_size != -1)
{
qDebug() << "data was resized properly; size: "<<resize_size;
data.resize(socket->pendingDatagramSize());
}
else
qDebug() << "data could not be resized(error)";
qint64 det_num;
det_num = socket->readDatagram(data.data(), 964, &cam_address, &cam_port);
qDebug() << "Can receive data(returns -1 if NO): "<<det_num;
//this returns nothing, too!
qDebug() << "Data is here: " << data.data();
}
Here's my code implementation result:
When signal is connected(), data could not be resized(error)
Can receive data(returns -1 if NO): -1
Data is here:
Connected!
QAbstractSocket::ConnectedState
When signal is readyRead(), Connected!
QAbstractSocket::ConnectedState data was resized properly; size: 0
Can receive data(returns -1 if NO): -1
Data is here:
readyRead signal sometimes seems NOT emitted as expected.
But it is obvious that any data is NOT being sent.
I've tried to find examples which are related to UDP network with a remote network. But there were few of them.
According to some threads, people recommended not to use connectToHost function on UDP network. However, I don't know how to make an approach to remote network without using connectToHost.
I want to know how I should correct my code to get packet from a remote network. Any advice will be very grateful for me because I'm a newbie to UDP network, and Qt.

Qt, send UDP through VPN(Hamachi)

I`m writing application, which send voice from one computer to other. I have simple implementation of "sender"
VoiceSender::VoiceSender(QAudioFormat &format, QString ip){
input = new QAudioInput(format);
QUdpSocket* socket = new QUdpSocket();
socket->connectToHost(ip, 14433);
input->start(socket);
}
Just get all data from mic and send it as UDP to specified IP.
In the other side I have program, which get all data received by UDP, and play it by audio system
Interlocutor::Interlocutor(QAudioFormat &format){
socket = new QUdpSocket();
socket->bind(QHostAddress::Any, 14433);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format))
format = info.nearestFormat(format);
output = new QAudioOutput(format);
device = output->start();
connect(socket, SIGNAL(readyRead()), this, SLOT(playData()));
}
void Interlocutor::playData()
{
qDebug() << QDateTime::currentDateTime();
while (socket->hasPendingDatagrams())
{
QByteArray data;
data.resize(socket->pendingDatagramSize());
socket->readDatagram(data.data(), data.size());
device->write(data.data(), data.size());
}
}
If both computers locating in the local network this works well, i can transfer my voice between computers. I tried to run it in the VPN. For it I run Hamachi in both computers, and got nothing. Slot playData() is never called. I run Wireshark and seen that computer get UDP packages, but Qt doesnt. What should I do to fix it.
Thanks.
You should check the result of the QUdpSocket::bind function.
bool QUdpSocket::bind ( const QHostAddress & address, quint16 port )
On success, the functions returns true and the socket enters
BoundState; otherwise it returns false.
if (!socket->bind(QHostAddress::Any, 14433))
{
QMessageBox::warning(0, "Error", "Binding Failed");
}
If binding is failed check if firewall is not blocking you or this port is not used by another application.

QTcpSocket state always connected, even unplugging ethernet wire

I have a QTcpSocket and I am reading into a loop. Each time a full packet has been read, or there has been an error, I manually check the status of the socket inside the loop, with:
while(true){
if(socket->state()==QAbstractSocket::ConnectedState){
qDebug()<<"Socket status: connected. Looking for packets...";
if(socket->waitForReadyRead(2000)){
//...
}
When I execute de program, once connected and the loop starts, it always prints qDebug()<<"Socket status: connected. Looking for packets..."; and then stucks at waitForReadyRead until some data is ready to be read.
The problem is that disconnections are not detected. If I disconnect from network from the OS options, or even if I unplug the ethernet wire, it behaves the same: Socket state equals QAbstractSocket::ConnectedState, so it goes on, but without receiving anything of course.
I also tried to detect disconnections connecting disconnected() signal (after fist connection) to a reconnect function:
// Detect disconnection in order to reconnect
connect(socket, SIGNAL(disconnected()), this, SLOT(reconnect()));
void MyClass::reconnect(){
qDebug()<<"Signal DISCONNECTED emitted. Now trying to reconnect";
panelGUI->mostrarValueOffline();
socket->close();
prepareSocket((Global::directionIPSerialServer).toLocal8Bit().data(), 8008, socket);
qDebug()<<"Reconnected? Status: "<<socket->state();
}
But signal is never emited, because this code is never executed. Which is logical, since it looks like socket state is always ConnectedState.
If I plug again, connection is restored and starts to receive data again, but I do want to detect disconnections to show "Disconnected" at the GUI.
Why is QTcpSocket behaving this way, and how can I solve this problem?
EDIT: I'm creating socket at the class constructor, and then initialising calling prepareSocket function:
socket = new QTcpSocket();
socket->moveToThread(this);
bool prepareSocket(QString address, int port, QTcpSocket *socket) {
socket->connectToHost(address, port);
if(!socket->waitForConnected(2000)){
qDebug()<<"Error creating socket: "<<socket->errorString();
sleep(1);
return false;
}
return true;
}
Finally found the solution in this Qt forum:
If no data is exchanged for a certain while, TCP will start sending
keep-alive segments (basically, ACK segments with the acknowledgement
number set to the current sequence number less one). The other peer
then replies with another acknowledgement. If this acknowledgment is
not received within a certain number of probe segments, the connection
is automatically dropped. The little problem is that the kernel starts
sending keep-alive segments after 2 hours since when the connection
becomes idle! Therefore, you need to change this value (if your OS
allows that) or implement your own keep-alive mechanism in your
protocol (like many protocols do, e.g. SSH). Linux allows you to
change it using setsockopt:
int enableKeepAlive = 1;
int fd = socket->socketDescriptor();
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
int maxIdle = 10; /* seconds */
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
int count = 3; // send up to 3 keepalive packets out, then disconnect if no response
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &count, sizeof(count));
int interval = 2; // send a keepalive packet out every 2 seconds (after the 5 second idle period)
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
I've been facing similar problems with a QT client app. Basically I handle it with Timers, signals and slots. When the app starts up, it starts a 4 second checkConnectionTimer. Every 4 seconds the timer expires, if the client socket state != AbstractSocket::Connected or Connecting, it attempt to connect with clientSocket->connectToHost
When the socket signals "connected()", it starts a 5 second server heartbeat timer. The server should send a one byte heartbeat message to its clients every 4 seconds. When I get the heartbeat (or any type of message signaled by readyRead()), I restart the heartbeat timer. So if the heartbeat timer ever has a timeout, I assume the connection to be down and it calls clientSocket->disconnectFromHost ();
This is working very well for all different kinds of disconnects on the server, graceful or otherwise (yanking cable). Yes it requires custom heartbeat type of stuff, but at the end of the day it was the quickest and most portable solution.
I wasn't to keen on setting KEEPALIVE timeouts in the kernel. This way its more portable.
In the constructor:
connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));
connect(clientSocket, SIGNAL(connected()), this, SLOT(socketConnected()));
connect(clientSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
connect(heartbeatTimer, SIGNAL(timeout()), this, SLOT(serverTimeout()));
...
// Other Methods
void NetworkClient::checkConnection(){
if (clientSocket->state() != QAbstractSocket::ConnectedState &&
clientSocket->state() != QAbstractSocket::ConnectingState){
connectSocketToHost(clientSocket, hostAddress, port);
}
}
void NetworkClient::readMessage()
{
// Restart the timer by calling start.
heartbeatTimer->start(5000);
//Read the data from the socket
...
}
void NetworkClient::socketConnected (){
heartbeatTimer->start(5000);
}
void NetworkClient::socketDisconnected (){
prioResponseTimer->stop();
}
void NetworkClient::serverTimeout () {
clientSocket->disconnectFromHost();
}
try this signal slot connection:
connect(this, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this, SLOT(onStateChanged(QAbstractSocket::SocketState)));
at slot implementation:
void TCPWorker::onStateChanged(QAbstractSocket::SocketState socketState ){
qDebug()<< "|GSTCPWorkerThread::onStateChanged|"<<socketState;
...}
I have the same problem, but instead your problem ( always connected ), i have delay 4-5 seconds to receive disconnect signals, after unplugget ethernet wire.
Still looking solution, post answer if find.
try my template of client in Qt:
class Client: public QTcpSocket {
Q_OBJECT
public:
Client(const QHostAddress&, int port, QObject* parent= 0);
~Client();
void Client::sendMessage(const QString& );
private slots:
void readyRead();
void connected();
public slots:
void doConnect();
};
on cpp:
void Client::readyRead() {
// if you need to read the answer of server..
while (this->canReadLine()) {
}
}
void Client::doConnect() {
this->connectToHost(ip_, port_);
qDebug() << " INFO : " << QDateTime::currentDateTime()
<< " : CONNESSIONE...";
}
void Client::connected() {
qDebug() << " INFO : " << QDateTime::currentDateTime() << " : CONNESSO a "
<< ip_ << " e PORTA " << port_;
//do stuff if you need
}
void Client::sendMessage(const QString& message) {
this->write(message.toUtf8());
this->write("\n"); //every message ends with a new line
}
i omitted some code as constructor and slots connections..
try with this and if it doesn t work maybe there is something wrong on server side..

Qt bidirectional client server using QTcpSocket and QTcpServer

I am trying to implement a bidirectional client-server program, where clients and servers can pass serialized objects between one another. I am trying to do this using Qt (QTcpSocket and QTcpServer). I have implemented programs like this in java, but I can't figure out how to do it using Qt. I've checked out the fortune client and fortune server examples...but from what I can see, the client is simply signaling the server, and the server sends it some data. I need for the client and server to send objects back and forth. I am not looking for a complete solution, all I am looking for is some guidance in the right direction.
I wrote some code, which accepts a connection, but does not accept the data.
SERVER
this class is the server; it should be accepting a connection and outputting the size of the buffer which is being sent. However it is outputting 0
#include "comms.h"
Comms::Comms(QString hostIP, quint16 hostPort)
{
server = new QTcpServer(this);
hostAddress.setAddress(hostIP);
this->hostPort = hostPort;
}
void Comms::attemptConnection(){
connect(server, SIGNAL(newConnection()), this, SLOT(connectionAccepted()));
//socket = server->nextPendingConnection();
server->listen(hostAddress,hostPort);
//receivedData = socket->readAll();
}
void Comms::connectionAccepted(){
qDebug()<<"Connected";
socket = new QTcpSocket(server->nextPendingConnection());
char* rec = new char[socket->readBufferSize()];
qDebug()<<socket->readBufferSize();
}
CLIENT
This class is the client. It should be sending the string 'hello'. It sends it successfully (to my knowledge)
#include "toplevelcomms.h"
#include "stdio.h"
TopLevelComms::TopLevelComms(QString hostIP, quint16 hostPort)
{
tcpSocket = new QTcpSocket();
hostAddress.setAddress(hostIP);
this->hostPort = hostPort;
}
void TopLevelComms::connect(){
tcpSocket->connectToHost(hostAddress,hostPort,QIODevice::ReadWrite);
//tcpSocket->waitForConnected(1);
QString string = "Hello";
QByteArray array;
array.append(string);
qDebug()<<tcpSocket->write(array);
}
Please tell me what I'm doing wrong, or tell me the general logic of establishing what I want in Qt.
QTcpSocket is asynchronous by default, so when you call connectToHost and write in same context it won't be sent, as socket is not connected. You should change your "client" code:
void TopLevelComms::connect(){
tcpSocket->connectToHost(hostAddress,hostPort,QIODevice::ReadWrite);
if(tcpSocket->waitForConnected()) // putting 1 as parameter isn't reasonable, using default 3000ms value
{
QString string = "Hello";
QByteArray array;
array.append(string);
qDebug()<<tcpSocket->write(array);
}
else
{
qDebug() << "couldn't connect";
}
}
Note: you also didn't check if you're able to listen
void Comms::attemptConnection(){
connect(server, SIGNAL(newConnection()), this, SLOT(connectionAccepted()));
//socket = server->nextPendingConnection();
if(server->listen(hostAddress,hostPort))
{
qDebug() << "Server listening";
}
else
{
qDebug() << "Couldn't listen to port" << server->serverPort() << ":" << server->errorString();
}
//receivedData = socket->readAll();
}
And last thing. Note that QTcpServer::nextPendingConnection() return QTcpSocket, so instead of taking that new connection you create new QTcpSocket with nextPendingConnection as parent
void Comms::connectionAccepted(){
qDebug()<<"Connected";
// WRONG! it will use QTcpSocket::QTcpSocket(QObject * parent)
//socket = new QTcpSocket(server->nextPendingConnection());
// use simple asign
socket = server->nextPendingConnection();
// move reading to slot
connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
}
now we will move reading to separate slot
void Comms::readSocket()
{
// note that dynamic size array is incompatible with some compilers
// we will use Qt data structure for that
//char* rec = new char[socket->readBufferSize()];
qDebug()<<socket->readBufferSize();
// note that QByteArray can be casted to char * and const char *
QByteArray data = socket->readAll();
}
I must admit, that it is a lot of errors as for such small code sample. You need to get some knowledge about TCP/IP connections. Those are streams and there is no warranty that whole data chunk will get to you at once
It looks like you have a timing issue. Since your client and server are different processes, there's no way you can guarantee that the entirety of TopLevelComms::connect() is being executed (along with the network data transfer) before your server's connectionAccepted() function tries to read from the socket.
I suspect that if you take advantage of QTcpSocket's waitForReadyRead() function, you should have better luck:
void Comms::connectionAccepted(){
qDebug()<<"Connected";
socket = new QTcpSocket(server->nextPendingConnection());
if( socket->waitForReadyRead() ) {
char* rec = new char[socket->readBufferSize()];
qDebug()<<socket->readBufferSize();
}
}