I am making a simple program that will 'connect' to itself and then send data. It starts a QTcpServer then waits for any incoming connections. I have a separate function that will in turn attempt to connect to this server at the localhost and port I decided on. This works when I open Telnet in the command prompt, but now in my actual program. Here is the code that I used (Some are snippets from other sources)
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
server = new QTcpServer(this);
//Initialize and start the server
connect(server, SIGNAL(newConnection()), this, SLOT(newConnection()));
if (!server->listen(QHostAddress::Any, 3665))
{
qDebug() << "Server failed to start!";
}
else
{
qDebug() << "Server started";
}
//Try to connect to the server
connectToServer("127.0.0.1", qint16(3665));
}
MainWindow::~MainWindow()
{
delete server;
delete ui;
}
void MainWindow::connectToServer(QString host, qint16 port)
{
qDebug() << "Connecting to " + host + " at port " + QString::number(port);
QTcpSocket socket;
socket.connectToHost(host, port);
if (!socket.waitForConnected(5000))
{
qDebug() << socket.errorString();
}
while (socket.bytesAvailable() < (int)sizeof(quint16))
{
if (!socket.waitForReadyRead(5000))
{
qDebug() << socket.errorString();
}
}
quint16 blockSize;
QDataStream in(&socket);
in.setVersion(QDataStream::Qt_5_5);
in >> blockSize;
while (socket.bytesAvailable() < blockSize)
{
if (!socket.waitForReadyRead(5000))
{
qDebug() << socket.errorString();
}
}
QString fortune;
in >> fortune;
qDebug() << fortune;
}
void MainWindow::newConnection()
{
qDebug() << "A connection has been found.";
QTcpSocket *socket = server->nextPendingConnection();
socket->write("hello client\r\n");
socket->flush();
socket->waitForBytesWritten(5000);
socket->close();
}
The source of your problem is, most likely, the pseudo-synchronous mess caused by waitFor methods. Get rid of them. Furthermore, you're not guaranteed anything about how many bytes you receive upon readyRead: it's perfectly normal to receive one byte at a time, in some circumstances, or really any number of bytes, including more bytes than you might expect. Your code must cope with that.
This is one example of such approach - it does what you want, asynchronously.
That is another example that shows how to leverage state machines to write asynchronous communications code using an easy to read, declarative syntax.
Related
I want to receive UDP messages using QT. The code I use (see bellow) works well, but the problem is that it only works for one message: after receiving one message, the code still running, but it seems that it doesn't receive anything anymore.
Indeed, after the first message received, the console display qDebug() << "in !";, meaning that it enters into the function, but never received other UDP messages.
I already check, I sure the message is well sent by the UDP server. So the problem must come from here. Any suggestions?
Launching UDP when the class is created:
App::App(QWidget *parent)
: QMainWindow(parent), imageLabel(new QLabel)
, scrollArea(new QScrollArea)
{
.....
StartUDP();
....
}
The UDP initialization:
void App::StartUDP()
{
socket = new QUdpSocket(this);
bool result = socket->bind(QHostAddress::AnyIPv4, 17);
qDebug() << result;
if(result)
{
qDebug() << "PASS";
}
else
{
qDebug() << "FAIL";
}
readyRead();
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()),Qt::QueuedConnection);
}
The function that what for UDP signal:
void App::readyRead()
{
qDebug() << "in !";
QHostAddress sender;
quint16 port;
while (socket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(socket->pendingDatagramSize());
socket->readDatagram(datagram.data(),datagram.size(),&sender,&port);
qDebug() <<"Message From :: " << sender.toString();
qDebug() <<"Port From :: "<< port;
qDebug() <<"Message :: " << datagram;
file_name = datagram;
m_SystemTrayIcon->showMessage(tr("Message"), tr("Nouveau fichier détecté"));
}
}
I am using Qt 4.8 GCC 32bit on xUbuntu 14.04.
I have the following piece of code, a TCP server that I use in order to get some remote commands and send back some answers - via TCP socket:
struct _MyRequest
{
unsigned long Request;
unsigned long Data;
} __attribute__((packed));
struct _MyAnswer
{
unsigned long Error;
unsigned long Filler;
} __attribute__((packed));
_MyRequest request;
_MyAnswer answer;
RemoteCmdServer::RemoteCmdServer(QObject * parent)
: QTcpServer(parent)
{
qDebug() << "Server started";
listen(QHostAddress("172.31.250.110"), 5004);
connect(this, SIGNAL(newConnection()), this, SLOT(processPendingRequest()));
}
void RemoteCmdServer::processPendingRequest()
{
qDebug() << "Process request";
QTcpSocket * clientConnection = nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()));
// get the request
int ret = clientConnection->read((char*)&request, sizeof(request));
qDebug() << "READ: " << ret;
if(ret == sizeof(request))
{
// send answer
clientConnection->write((char*)&answer, sizeof(answer));
}
qDebug() << "Disconnecting...";
clientConnection->disconnectFromHost();
}
I am able to write correctly if I comment the if(ret == sizeof(request)) line.
Yet, I can't read from the socket (I always get 0 bytes).
I am 100% sure that the TCP-tool I use to send packets to my app works ok.
Here is the debug output from my app:
Server started
Process request
READ: 0
Disconnecting...
What am I doing wrong? Please advise!
You should wait for the data either in a non-blocking or blocking way. You can use waitForReadyRead to do it in a blocking way.
void RemoteCmdServer::processPendingRequest()
{
qDebug() << "Process request";
QTcpSocket * clientConnection = nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()));
if (clientConnection->waitForReadyRead())
{
// get the request
QByteArray message = clientConnection->readAll(); // Read message
qDebug() << "Message:" << QString(message);
}
else
{
qDebug().nospace() << "ERROR: could not receive message (" << qPrintable(clientConnection->errorString()) << ")";
}
qDebug() << "Disconnecting...";
clientConnection->disconnectFromHost();
}
You're trying to read data from the new connection without returning to the Qt event loop -- I don't think that's going to work.
After you've accepted the connect with...
QTcpSocket * clientConnection = nextPendingConnection();
You need to connect to its readyRead signal with something like...
connect(clientConnection, SIGNAL(readyRead()), this, SLOT(my_read_slot()));
Where my_read_slot is the member function that will actually perform the read operation.
I am writing simple client server program in Qt that server is multi thread.
For one server it work correctly and it can send message from client to server but in multi thread form it doesn't work, it connect to thread and also show the message "client connected" but it can't show message sent from client!
I searched a lot bud I couldn't find what is the problem and any solution for it.. Here is my code:
Could you please help me. Thanks in advance.
myserver.cpp
#include "myserver.h"
#include "mythread.h"
myserver::myserver(QObject * parent): QTcpServer(parent)
{
}
void myserver::startserver()
{
int port = 6666;
if (!this - > listen(QHostAddress::Any, port)) {
qDebug() << "Could not start server ";
} else {
qDebug() << "Listening to port ";
}
}
void myserver::incomingConnection(qintptr socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
mythread * thread = new mythread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread - > start();
}
mythread.cpp
#include "mythread.h"
#include "myserver.h"
mythread::mythread(qintptr ID, QObject *parent) : QThread(parent)
{
this->socketDescriptor = ID;
}
void mythread::run()
{
qDebug() << " Thread started";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor)) {
emit error(socket->error());
return;
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
qDebug() << socketDescriptor << " Client connected";
}
void mythread::readSocket()
{
QByteArray Data = socket->readAll();
qDebug()<< socketDescriptor <<" Data in: " << Data;
socket->write(Data);
}
If you read the documentation for the QThread::run function you will see
Returning from this method will end the execution of the thread.
You need to call the QThread::exec function to enter the thread event loop.
I have a server that can handle multiple threads. The server starts and listens, but it is having trouble echoing when an incoming connection is pending.
I am using telnet to open the socket and send data to the server. However, the server only displays that it's listening, but doesn't echo any of the data I type through telnet or signify that there is an incoming connection. I shut off Windows firewall for private networks and still...nothing.
Also tried seeing if the server error string had anything useful to say, but all it is just an empty string.
This is a complete mystery to me and if anyone had anything constructive to note, it'd be much appreciated. Code for the thread and server is below.
server.cpp
#include "myserver.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::StartServer()
{
if(!this->listen(QHostAddress::Any,1234))
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "Listening...";
}
}
void MyServer::incomingConnection(int socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
MyThread *thread = new MyThread(socketDescriptor,this);
connect(thread, SIGNAL(finished()),thread, SLOT(deleteLater()));
thread->start();
}
thread.cpp
#include "mythread.h"
MyThread::MyThread(int ID, QObject *parent) :
QThread(parent)
{ this->socketDescriptor = ID;
}
void MyThread::run()
{
qDebug() << socket->errorString();
//thread starts here
qDebug() << socketDescriptor << " Starting thread";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor))
{
emit error(socket->error());
return;
}
connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::DirectConnection);
connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()),Qt::DirectConnection);
qDebug() << socketDescriptor << " Client Connected";
exec();
}
void MyThread::readyRead()
{
QByteArray Data = socket->readAll();
qDebug() << socketDescriptor << " Data in: " << Data;
socket->write(Data);
}
void MyThread::disconnected()
{
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}
Which version of Qt are you using? In Qt 5, the parameter for the function incomingConnection is of type qintptr and not int. Have a look at the following links:
incomingConnection - Qt 5
Qt 5 - Multithreaded server tutorial
I'm trying to establish bluetooth connection between laptop and Samsung Smart Touch Remote. My issue is that I can't connect socket to device(socket is always in "Host lookup state"):
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Create a discovery agent and connect to its signals
QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
connect(discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)),
this, SLOT(deviceDiscovered(const QBluetoothDeviceInfo&)));
// Start a discovery
discoveryAgent->start();
}
void MainWindow::deviceDiscovered(const QBluetoothDeviceInfo &device)
{
socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this);
socket->connectToService(QBluetoothAddress(device.address()),
QBluetoothUuid(QBluetoothUuid::SerialPort));
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)),
this, SLOT(socketError(QBluetoothSocket::SocketError)));
connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
connect(socket, SIGNAL(readyRead()), this, SLOT(socketRead()));
connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), this, SLOT(socketStateChanged()));
}
void MainWindow::socketRead()
{
QByteArray receivedData = socket->readAll();
QMessageBox msg;
msg.setText(QString(receivedData));
msg.exec();
}
void MainWindow::socketConnected()
{
qDebug() << "Socket connected";
qDebug() << "Local: "
<< socket->localName()
<< socket->localAddress().toString()
<< socket->localPort();
qDebug() << "Peer: "
<< socket->peerName()
<< socket->peerAddress().toString()
<< socket->peerPort();
}
void MainWindow::socketDisconnected()
{
qDebug() << "Socket disconnected";
socket->deleteLater();
}
void MainWindow::socketError(QBluetoothSocket::SocketError error)
{
qDebug() << "Socket error: " << error;
}
void MainWindow::socketStateChanged()
{
int socketState = socket->state();
QMessageBox msg;
if(socketState == QAbstractSocket::UnconnectedState)
{
msg.setText("unconnected");
}
else if(socketState == QAbstractSocket::HostLookupState)
{
msg.setText("host lookup");
}
else if(socketState == QAbstractSocket::ConnectingState )
{
msg.setText("connecting");
}
else if(socketState == QAbstractSocket::ConnectedState)
{
msg.setText("connected");
}
else if(socketState == QAbstractSocket::BoundState)
{
msg.setText("bound");
}
else if(socketState == QAbstractSocket::ClosingState)
{
msg.setText("closing");
}
else if(socketState == QAbstractSocket::ListeningState)
{
msg.setText("listening");
}
msg.exec();
}
Can someone please tell me what I'm doing wrong?
Have you tried to open a COM port on your Laptop which is connected to the Laptop's bluetooth module?
You can go to Bluetooth settings -> Com Ports -> Add a new com port. Then open this Port using hypertermical or Teraterm. Now try to connect from your Android phone...
Hope this works!
I had the samme issue. The fix was to use a port 1 in argument to socket->connectToService(addr, 1).
This tells SDP to use connection as channel via SDP.