Qt UDpsocket working on same computer but not on two computers on same network - c++

I am able to send and receive to two different programs running on same computer. But not able to do the same when running them on different computers. Both computers are on same Local area network. I am working on windows 10.
#include "communicationmanager.h"
communicationManager::communicationManager(int portNumber,int socketRole)
{
//socketRole:0=Sender 1=Reciever
//socket = new QUdpSocket(this);
PortNumber = portNumber;
socket = new QUdpSocket(this);
if(socketRole == 1)
{
socket->bind(QHostAddress::LocalHost,PortNumber);
connect(socket, SIGNAL(readyRead()), this, SLOT(recieve()));
}
}
communicationManager::~communicationManager()
{
//delete socket;
}
void communicationManager::prepareMessage(QString command,QString message,int recieverID)
{
Command = command;
Message = message;
recieverID = recieverID;
}
void communicationManager::send()
{
QByteArray datagram;
QDataStream out(&datagram, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_13);
out<<Command<<Message<<recieverID;
socket->writeDatagram(datagram, QHostAddress::LocalHost, PortNumber);
}
void communicationManager::recieve()//For recieving data
{
qDebug()<<"recieve";
QByteArray datagram;
do
{
datagram.resize(socket->pendingDatagramSize());
socket->readDatagram(datagram.data(), datagram.size());
} while (socket->hasPendingDatagrams());
QDataStream in(&datagram, QIODevice::ReadOnly);
QString command;
QString message;
int recieverID;
in >>command>>message>>recieverID;
}

You need to bind to QHostAddress::Any in order to actually receive packets from outside the local machine. QHostAddress::LocalHost will only receive traffic from the same physical machine.

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.

Trying to access to camera connected by LAN using Qt Network

I am trying to get data from a LAN-connected infrared camera.
I don't know how to approach packets from the external network.
Here's my code.
The code below was run on Qt 5.9.7 (msvc2017_64) I've changed codes from Qt UDP example. (https://www.bogotobogo.com/Qt/Qt5_QUdpSocket.php)
#include "myudp.h"
MyUDP::MyUDP(QObject *parent) :
QObject(parent)
{
// create a QUDP socket
socket = new QUdpSocket(this);
socket_cam = new QUdpSocket(this);
// The most common way to use QUdpSocket class is
// to bind to an address and port using bind()
// bool QAbstractSocket::bind(const QHostAddress & address,
// quint16 port = 0, BindMode mode = DefaultForPlatform)
socket->bind(QHostAddress::LocalHost, 1234);
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
void MyUDP::HelloUDP()
{
QByteArray Data;
QHostAddress camera_loc = QHostAddress("192.168.10.197");
quint16 cameraPort = 32197;
qint64 deg_num = socket->readDatagram(Data.data() ,964, &camera_loc,
&cameraPort);
qDebug() << "Deg_num: " << deg_num; //this returns -1. Therefore, it
seems it can't read any data from camera_loc.
// Sends the datagram datagram
// to the host address and at port.
// qint64 QUdpSocket::writeDatagram(const QByteArray & datagram,
// const QHostAddress & host, quint16 port)
socket->writeDatagram(Data, QHostAddress::LocalHost, 1234);
}
void MyUDP::readyRead()
{
// when data comes in
QByteArray buffer;
buffer.resize(socket->pendingDatagramSize());
QHostAddress sender = QHostAddress("192.168.10.197");
quint16 senderPort = 32197;
// qint64 QUdpSocket::readDatagram(char * data, qint64 maxSize,
// QHostAddress * address = 0, quint16 * port = 0)
// Receives a datagram no larger than maxSize bytes and stores it
// The sender's host address and port is stored in *address and *port
// (unless the pointers are 0).
socket->readDatagram(buffer.data(), buffer.size(),
&sender, &senderPort);
qDebug() << "Message from: " << sender.toString();
qDebug() << "Message port: " << senderPort;
qDebug() << "Message: " << buffer;
}
As I've seen on Wireshark, packets arrived correctly as I expected.
However, my code doesn't work as I expected. (readDatagram on camera_loc returns (-1))
According to other threads, we don't need to connect them because UDP communication doesn't need to make connections.
What I want to make with this code is as follow.
(0. Save data from the camera (192.168.10.197) on a variable using readDatagram) I am not sure this is a really necessary process...
1. Write data to buffer as written in this code (using writeDatagram function).
I could not find solutions even if I struggled.
I thought it would be easy but it wasn't ...
Any advice will be very grateful because I am a newbie to qt and UDP network.
Thanks in advance.

UDP incoming packets not visible in Qt

I'm trying to receive UDP packets from an Arduino Uno. Packets are received by the computer(they're visible in wireshark), but aren't seen in my Qt application. There part of my Udp class:
#include "udp.h"
Udp::Udp(QHostAddress adr, quint16 pr) : QObject()
{
address.setAddress(adr.toString());
port = pr;
socket = new QUdpSocket();
status = socket->bind(address,port);
connect(socket,SIGNAL(readyRead()), this, SLOT(readUdp()));
}
void Udp::sendUdp(QByteArray out)
{
socket->writeDatagram(out,address,port);
}
QByteArray Udp::readUdp()
{
QByteArray input;
input.resize(socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
socket->readDatagram(input.data(),input.size(),
&sender,&senderPort);
return input;
}
socket->pendingDatagramSize() returns 0(and -1 sometimes).
I do not know QT, but when using berkely socket API, you need to ensure endian
port = htons(pr);
When your application is running, you can run netstat -l in a terminal. Your application should appear on the list

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.

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();
}
}