Cannot write data to Serial Port - c++

I am trying to write data to Serial Port. I use this way:
QBluetoothSocket *socket;
socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
socket->open(QIODevice::WriteOnly);
QByteArray byteArr;
QDataStream out(&byteArr, QIODevice::WriteOnly);
out << 1 << '\n'; //if plusbutton is pushedm then send zero
socket.write(byteArr);
qDebug()<<socket.write(byteArr)<<endl;
But I get in return:
W/libA_for_w8.so( 6443): (null):0 ((null)): qt.bluetooth.android:
Socket::writeData: QBluetoothSocket::ConnectingState false
W/libA_for_w8.so( 6443): (null):0 ((null)): qt.bluetooth.android:
Socket::writeData: QBluetoothSocket::ConnectingState false
D/libA_for_w8.so( 6443): ..\A_for_w8\widget.cpp:68 (void Widget::on_plus_clicked()): -1
D/libA_for_w8.so( 6443):
So, nothing is written to there.
It seems, that the code is ok, but it doesn't work.
Can you tell me what's wrong?
Thank you.
P.S.
I checked socket is open .
socket->isOpen return true and I get:
W/libA_for_w8.so( 9638): (null):0 ((null)): qt.bluetooth.android: Socket::writeData: QBluetoothSocket::UnconnectedState false
D/libA_for_w8.so( 9638): ..\A_for_w8\widget.cpp:70 (void Widget::on_plus_clicked()): -1

You need to connect the socket to an endpoint before you can successfully write anything. There must be a running Bluetooth service somewhere, to which you connect using connectToService(). After the connected() signal has been emitted, you can write data.
It doesn't appear that QBluetoothSocket has a waitForConnected() function, as QAbstractSocket and its subclasses do. This means you can use something like QSignalSpy to wait for the connected() signal, or, if you don't care so much about efficiency, just a busy-wait loop would do.
EDIT:
As pointed out in the comment, waiting for events to happen is the whole point of Qt's main event loop. Using the waitFor* methods or another event loop is pretty inefficient, and definitely goes against the spirit of Qt. So the best solution to writing data only after the socket is connected is to connect a writeData() slot to the connected() signal of QBluetoothSocket.

Related

The slot of readMessageFromTCPServer could not be triggered sometimes after receiving message

I use Qt creator 5.5.1 in windows 7.
The compiler is VC 2010 32 bits.
I have written a socket client. It could connect well but sometimes its readyRead() signal could not be triggered after receiving message from server. So the readMessageFromTCPServer() slot could not be triggered and the thread could not run.
void MainWindow::on_pushBtn_LoadCfg_clicked()
{
if (tcpClient == NULL)
{
tcpClient = new QTcpSocket;
tcpClient->connectToHost(ui->txtIPServer->text(),ui->txtPortServer-
>text().toInt());
QObject::connect(tcpClient,SIGNAL(readyRead()),this,
SLOT(readMessageFromTCPServer()));
}
}
void MainWindow::readMessageFromTCPServer()
{
std::string r="start";
QByteArray qba;
qba= tcpClient->readAll();
if (qba.contains(r.c_str()))
{
cout<<"thread run";
}
}
When I tried to debug this program. I put a break point at this line: Sleep(800), but sometimes this slot could not be triggered after receiving message from socket server. And I have checked that the socket is still connected, why the slot could not be triggered?
There are some errors in your code. You will only have the slot triggered once.
Get rid of those Sleep commands. There is no good reason to use it if you are doing it in the main thread.
QByteArray qba= NULL; makes no sense. QByteArray qba; is ok.
while(1) means forever. You should break the loop at some point. Actually, you do not need this loop at all. Put the code inside this loop out of it and remove the loop. When the readyRead() signal is emitted, it means that there is some data to be read. You can readAll() that data chunk, do your stuff and return.
There is no guarantee that you will get your entire message in one round. So, in some circumstances, you may get "St" in one signal and "art" in another. So, you should implement your own buffering mechanism for such a situation. It may happen on big chunks of data. If you are sure that you are getting very short packages, then it's ok to rely on the internal buffer of QTCPSocket.

UnrealEngine4: Recv function would keep blocking when TCP server shutdown

I use a blocking FSocket in client-side that connected to tcp server, if there's no message from server, socket thread would block in function FScoket::Recv(), if TCP server shutdown, socket thread is still blocking in this function. but when use blocking socket of BSD Socket API, thread would pass from recv function and return errno when TCP server shutdown, so is it the defect of FSocket?
uint32 HRecvThread::Run()
{
uint8* recv_buf = new uint8[RECV_BUF_SIZE];
uint8* const recv_buf_head = recv_buf;
int readLenSeq = 0;
while (Started)
{
//if (TcpClient->Connected() && ClientSocket->GetConnectionState() != SCS_Connected)
//{
// // server disconnected
// TcpClient->SetConnected(false);
// break;
//}
int32 bytesRead = 0;
//because use blocking socket, so thread would block in Recv function if have no message
ClientSocket->Recv(recv_buf, readLenSeq, bytesRead);
.....
//some logic of resolution for tcp msg bytes
.....
}
delete[] recv_buf;
return 0
}
As I expected, you are ignoring the return code, which presumably indicates success or failure, so you are looping indefinitely (not blocking) on an error or end of stream condition.
NB You should allocate the recv_buf on the stack, not dynamically. Don't use the heap when you don't have to.
There is a similar question on the forums in the UE4 C++ Programming section. Here is the discussion:
https://forums.unrealengine.com/showthread.php?111552-Recv-function-would-keep-blocking-when-TCP-server-shutdown
Long story short, in the UE4 Source, they ignore EWOULDBLOCK as an error. The code comments state that they do not view it as an error.
Also, there are several helper functions you should be using when opening the port and when polling the port (I assume you are polling since you are using blocking calls)
FSocket::Connect returns a bool, so make sure to check that return
value.
FSocket::GetLastError returns the UE4 Translated error code if an
error occured with the socket.
FSocket::HasPendingData will return a value that informs you if it
is safe to read from the socket.
FSocket::HasPendingConnection can check to see your connection state.
FSocket::GetConnectionState will tell you your active connection state.
Using these helper functions for error checking before making a call to FSocket::Recv will help you make sure you are in a good state before trying to read data. Also, it was noted in the forum posts that using the non-blocking code worked as expected. So, if you do not have a specific reason to use blocking code, just use the non-blocking implementation.
Also, as a final hint, using FSocket::Wait will block until your socket is in a desirable state of your choosing with a timeout, i.e. is readable or has data.

QTcpSocket Read Error

I have a Qt based TCP client and server making use of QTcpServer and QTcpSocket classes for communication. The server is compiled using Qt 5.3.1 and the client is compiled using Qt 4.8.1. This is done so because the client is a part of a framework that uses Qt 4.8.1 running on Ubuntu 12.04.
Since the classes I make use is available in both Qt versions I assume this wont create a problem.
However my client has some weird issues that it does not receive data from the server! I checked the server side and the data is sent from the server and I can also see the data packet on the wire using wireshark. However on my client code, the data does not arrive!
I investigated this a bit and it led me to a strange conclusion that this happens only if I use the read method of QTcpSocket! If I use the native POSIX read system call, I am able to read the data correctly! Please see my code below:
qDebug() << "QTcpSocket::bytesAvailable() gives" << m_pSocket->bytesAvailable();
char nData;
qint32 szReceived;
if(sizeof(char) != (szReceived = m_pSocket->read((char*)&nData,sizeof(char))))
{
qDebug() << "Error reading data from QTcpSocket::read()" << m_pSocket->errorString();
}
else
{
qDebug() << "QTcpSocket::read() returned" << szReceived;
}
int nDesc = m_pSocket->socketDescriptor();
if(sizeof(char) != (szReceived = read(nDesc, &nData,sizeof(char))))
{
perror("Error reading data from POSIX read()");
}
else
{
qDebug() << "POSIX read() returned" << szReceived;
}
This produces the following output:
QTcpSocket::bytesAvailable() gives 0
Error reading data from QTcpSocket::read() "Network operation timed out"
POSIX read() returned 1
How is it that the POSIX system calls reads the buffered data as expected and the Qt class cannot read it? Plus I have not set any socket options and so I don't know why it reports an error that network operation timed out!
"read" is a blocking call in POSIX, it waits till the data is arrived. while QTcpSocket is non-blocking operation it immediately returns the buffered data. Call waitForReadyRead before doing a read
socket->waitForReadyRead();
if(sizeof(char) != (szReceived = m_pSocket->read((char*)&nData,sizeof(char))))
I think that it is misuse of QTcpSocket concept. QTcpSocket implements asynchronous architecture while POSIX read/write calls are blocking until the success or error of I/O on socket. It is much better to process read in slot for readyRead signal. Consider this:
class MyClient
{
Q_OBJECT
...
private slots:
readFromSocket();
};
In your intialization:
QObject::connect(
m_pSocket, SIGNAL(readyRead()),
this, SLOT(readFromSocket()));
And real job done here:
void
MyClient::readFromSocket()
{
QByteArray buffer = m_pSocket->readAll();
// All your data in buffer.
}
I'm aware of the non-blocking nature of QTcpSocket and blocking nature of POSIX read call. Unfortunately I cannot use the signal readFromSocket because my communication architecture expects a header to be sent before each communication (TCP way) to see the payload that is streamed for that particular message. Hence I have to wait till I receive at least the header.
I do believe that this has something to do with the mode (blocking or non-blocking). I did some more tests and none of them were conclusive. In one of my tests, I tried to call a waitForReadyRead with a timeout of 1ms, 2ms, 3ms. This still wasn't sufficent for the read to succeed! I doubt if the read would need such time to read from the kernel buffers to user space as I can clearly see from wireshark that the message was received within 400ms.
When I give -1 as the timeout value of waitForReadyRead, the read succeeds! To put it in another way, the read succeeds only when the socket waits indefinitely like in the case of POSIX read call.
Another strange thing I observed was, this issue was originally observed when I was running a server compiled using Qt 5.3.1 and client compiled using Qt 4.8.1. When I compile my client to use Qt 5.3.1, I do not see this problem!!! I even tried compiling using Qt 4.7.1 and it worked without any issues!!!
Are there any known issues with socket implementation of Qt 4.8.1? I couldn't find much info regarding this unfortunately.

Answer an UDP packet

I have a UDP server using the following code:
void initialize()
{
connect(&_udpSocket, SIGNAL(readyRead()), this, SLOT(onUdpDatagram()));
_udpSocket.bind(QHostAddress::Any, 28283);
}
void onUdpDatagram()
{
qDebug() << "udp packet received!";
_udpSocket.write("Hello");
}
Unfortunately when a UDP packet is received, I have the following error in the log:
QIODevice::write: device not open
How can I make the UDP socket writable? I tried to create another socket for the answer that connect to the sender address and port but the sending won't use the 28283 port anymore...
Any idea?
For info: I'm using Qt 5.2.1 on MacOS 10.9
UDP is not a connection-based protocol. You don't get a separate socket for each peer, instead there's one socket for all communication on a single port.
Therefore, there's some extra effort needed to reply to an incoming UDP packet. You need to retrieve the sender address from the datagram you received, and send back to that same address. In the sockets API this is done by using recvfrom and sendto functions instead of recv (or read) and send (or write) -- the latter are designed for connected sockets like you use with TCP.
You didn't show the declaration (really, the type) for your _udpSocket variable, so I'm assuming that you are using a QUdpSocket. In that case, it looks like you will want to use the readDatagram and writeDatagram functions, which like recvfrom and sendto, have an additional parameter for the peer address (actually, it's a pair, one for the IP address, one for the port).
Here's what the Qt documentation says about that:
The most common way to use this class is to bind to an address and port using bind(), then call writeDatagram() and readDatagram() to transfer data. If you want to use the standard QIODevice functions read(), readLine(), write(), etc., you must first connect the socket directly to a peer by calling connectToHost().
Coincidentally, this warning was introduced by me in Qt upstream:
QIODevice::write: device not open
It should be pretty clear unlike before the introduction of this, namely: you have forgotten to connect to the host with your udp socket. You cannot expect it to write and/or read if it is not even open and/or connected. See the documentation for details:
If you want to use the standard QIODevice functions read(), readLine(), write(), etc., you must first connect the socket directly to a peer by calling connectToHost().
You have to do something like this somewhere in your code:
_udpSocket.connectToHost(myHostAddress, 28283, ReadWrite, AnyIPProtocol);
The last two parameters can be skipped as they are the default. As you can read from the documentation, this method call will open the socket for you, too, which is necessary to get done for QIODevice read and write operations.
That being said, you really should not neglect error checking in your code as it currently seems to stand. It will be difficult to find the issues this way.
Also, it is ice on the cake, but I would encourage you to start using the "new" signal-slot syntax, which is not so new, but much more modern and handier:
void initialize()
{
connect(&_udpSocket, &QUdpSocket::connected, [&_udpSocket]() {
connect(&_udpSocket, &QUdpSocket::readyRead, [&_udpSocket]() {
qDebug() << "udp packet received!";
if (_udpSocket.write("Hello") != 6)
qDebug() << "Failed to write:" << _udpSocket.errorString();
});
});
connect(&_udpSocket, &QUdpSocket::error, [&_udpSocket]() {
qDebug() << "Error occured:" << _udpSocket.errorString();
});
_udpSocket.connectToHost(myHostAddress, 28283, ReadWrite, AnyIPProtocol);
}

Can QSslSocket be used immediately after startServerEncryption()?

After I've called QSslSocket::startServerEncryption(), can I proceed to immediately use the socket as an ordinary QTcpSocket, reading and writing data from it, or do I need to call waitForStartEncrypted() before using it?
socket->startServerEncryption();
socket->waitForEncrypted(); // <==== Is this line necessary?
socket->write(data);
QByteArray response = socket->read();
You can start to use it immediately. The data will be buffered and sent later. Note that you can't read any data from it yet, since none will have arrived. The actual connection and handshake will not occur until you enter the event loop.