Qt Socket not waiting for bytes written - c++

I wrote a chess client/server mobile application and have a remote server that has been tested on the West Coast, the East Coast, in between, etc. The program is this in a nutshell:
1. Log in to remote server with correct username/password via iOS/Android or Windows desktop.
2. Enter queue for a 1-minute, 5-minute or 30-minute game of chess.
3. Wait for another opponent to join queue.
4. Get matched and play game of chess.
5. When game is over, log out or play more chess.
I am getting the weirdest freaking error when I log in to the server via my school's internet, however. This is so weird because it the ONLY ISP that has problems out of the many ISP's I have connected from.
When I log into the server through my school's internet, I will get the following error and errorString from my socket.
QAbstractSocket::UnknownSocketError "Unknown error"
The steps to produce this in my application are:
1. Enter username and password, log into server. (Successfully completes this).
2. Click to join a queue for a game of chess. (Successfully writes to socket, but fails to wait for bytes written then emits the above error and error string.
I checked the server and readyRead() is not even called, so I know the client is not sending anything to the server.
The funny thing is, I found a workaround for getting past this error.
1. Click on Settings page.
2. Click Save. (Does the exact same thing as I try to do above. Write to socket, flush and wait for bytes written).
3. Join queue (Successfully joins queue).
The workaround MAKES NO SENSE since it does not do anything differently than what I tried to do above (write to socket, flush and wait for bytes written).
Does anyone have a clue on what might be going on?
Why is this error specific to ONE internet location? My school internet is slow as hell, but doesn't explain why the socket is disconnected immediately in the function below.
Why does my workaround work?
What can I do to learn more about my problem (i.e. stupid error message..."unknown error").
Not only this, but when I right-click on the function below, then click 'Find usages', the build folder appears. This is the only function in the program that does this. WTF???
Socket disconnects in this function.
void CG_serverConnection::sendQueueType(int timeControl)
{
//Create local JSON object
QJsonObject userInfo;
//Create object
userInfo["PacketHeader"] = QUEUE_REQUEST;
userInfo["TimeControl"] = timeControl;
//Create JSON document
QJsonDocument doc;
doc.setObject(userInfo);
qDebug() << "Send queue type called! ";
qDebug() << doc.toJson();
QByteArray byteArray = doc.toBinaryData();
//Send over socket
if(m_socket->write(byteArray))
{
qDebug() << "Wrote to socket";
}
else
m_socket->errorString();
if(m_socket->flush())
{
qDebug() << "Flushed";
}
else
qDebug() << m_socket->errorString();
if(m_socket->waitForBytesWritten(50000))
{
qDebug() << "Bytes were written.";
}
else
{
qDebug() << m_socket->error();
qDebug() << m_socket->errorString();
}
}
Where I call the function
Button
{
id: btn_oneMinuteGame
text: "One Minute"
style: cgButtonStyle
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: Lobby.getControlWidth()
Layout.preferredHeight: Lobby.getControlHeight()
onClicked:
{
ServerConnection.sendQueueType(1) // TODO : Magic numbers
root.startOneMinuteGame()
}
}

For some reason if I call this at the top of my function, everything works...
Makes no sense. If someone can explain why this works or you have another solution, please post it.
//Temporary bug fix
this->sendUpdatedUserInfo();
Function I call that somehow makes everything work
void CG_serverConnection::sendUpdatedUserInfo()
{
QJsonObject request;
request["PacketHeader"] = UPDATE_INFO;
request["loggedIn"] = m_player.loggedIn;
request["banned"] = m_player.banned;
request["username"] = m_player.username;
request["elo"] = m_player.elo;
request["countryFlag"] = m_player.countryFlag;
request["pieceSet"] = m_player.pieceSet;
request["language"] = m_player.language;
request["sound"] = m_player.sound;
request["coordinates"] = m_player.coordinates;
request["arrows"] = m_player.arrows;
request["autoPromote"] = m_player.autoPromote;
request["boardTheme"] = m_player.boardTheme;
QJsonDocument doc;
doc.setObject(request);
qDebug() << "Updated userInfo being sent: ";
qDebug() << doc.toJson();
m_socket->write(doc.toBinaryData());
m_socket->flush();
m_socket->waitForBytesWritten();
}

Related

How can i mock a serial port UART linux

Preface
So basically im doing a project for a extracurricular activity and it involves having a microcontroller read some data from a CAN bus and then send that data over through a UART serial connection to a bananaPi Zero M2 thats currently running arch linux.
The microcontroller is probably an arduino of some kind(most likely a modified version of it), the problem resides with the constant change of the project, and since i want my code to survive longer than a year a part of that is creating tests, ive been looking for a way to emulate the serial connection that is made from the bananaPi (on file/dev /dev/ttyS0) to the microcontroller so that i dont have to constantly compile the code for the bananaPi set everything up just to check if "hello" is being correctly sent over the serial line. The thing is i havent found a way to sucessfully virtualize a serial port
Attempts
So i've looked a bit on options and i found socat, apparently it can redirect sockets and all kinds of connections and especially baud rates(although personally its not really that relevant for giving credence to the tests to my colleagues is of the most importance) So i spent a evening trying to learn three things at once and after a lot of problems and a lot of learning i came to this
void Tst_serialport::sanityCheck(){
socat.startDetached("socat -d -d pty,rawer,b115200,link=/tmp/banana, pty,rawer,b115200,link=/tmp/tango");
sleep(1);
_store = new store("/tmp/banana");
QCOMPARE(_store->dev,"/tmp/banana");
}
void Tst_serialport::checkSendMessage(){
QSerialPort tango;
tango.setPortName("/tmp/tango");
tango.setBaudRate(QSerialPort::Baud115200);
tango.setDataBits(QSerialPort::Data8);
tango.setParity(QSerialPort::NoParity);
tango.setStopBits(QSerialPort::OneStop);
tango.setFlowControl(QSerialPort::NoFlowControl);
tango.open(QIODevice::ReadWrite);
tango.write("Hello");
tango.waitForBytesWritten();
tango.close();
QCOMPARE(_store->lastMessage,"Hello");
}
void Tst_serialport::closeHandle(){
socat.close();
}
QTEST_MAIN(Tst_serialport)
The intent here being that in sanityCheck a fake serial device would be created on /tmp/banana and /tmp/tango that would redirect io between each other so that when _store started listening to banana and i sent a message to tango i would receive that same message inside the store object
The thing is the function that is waiting for messages, etc... isnt triggering even tough ive managed to work with it when i had an arduino plugged directly to my computer
before continuing im sorry that the code is kinda all messed up, im kinda new to both qt and c++, although i have some experience with C which made me use a lot of C stuff when i shouldve sticked with qt. Unfortunately i havent had much time to refactor everything to a more clean version of the code
Here's the other side
int store::setupSerial() {
QSerialPort* serial= new QSerialPort();
serial->setPortName(this->dev);
serial->setBaudRate(QSerialPort::Baud115200);
serial->setDataBits(QSerialPort::Data8);
serial->setStopBits(QSerialPort::OneStop);
serial->setParity(QSerialPort::NoParity);
serial->setFlowControl(QSerialPort::NoFlowControl);
if (!serial->open(QIODevice::ReadOnly)) {
qDebug() << "Can't open " << this->dev << ", error code" << serial->error();
return 1;
}
this->port = serial;
connect(this->port, &QSerialPort::readyRead, this, &store::handleReadyRead);
connect(this->port, &QSerialPort::errorOccurred, this, &store::handleError);
return 0;
}
store::store( char * dev, QObject *parent ): QObject(parent){
if (dev == nullptr){
// TODO: fix this(use a better function preferably one handled by QT)
int len = sizeof(char)*strlen(DEFAULT_DEVICE)+1;
this->dev = (char*)malloc(len);
strcpy(this->dev,DEFAULT_DEVICE);
}
//copy dev to this->dev
else{
int len = sizeof(char)*strlen(dev)+1;
this->dev = (char*)malloc(len);
strcpy(this->dev,dev);
}
setupSerial();
}
void store::handleReadyRead(){
bufferMessage=port->readAll();
serialLog.append(bufferMessage);
//can be optimized using pointers or even a variable as a "bookmark" wether a int or pointer
lastMessage.append(bufferMessage);
uint32_t size = (int)lastMessage[0] | (int)lastMessage[1] << 8 | (int)lastMessage[2] << 16 | (int)lastMessage[3] << 24;
int8_t eof = 0x00;
if((bool)((long unsigned int)lastMessage.size() == size+sizeof(size)+sizeof(eof))&& ((bool) lastMessage[lastMessage.size()-1] == eof)){
parseJson();
//clear lastMessage()
lastMessage.clear();
}
}
//... some other code here
If you're wondering whats the output or the result well
11:23:40: Starting /home/micron/sav/Trabalhos/2022-2023/FormulaStudent/VolanteAlphaQT/build-VolanteAlphaQT-Desktop-Testing/bin/VolanteAlphaQT_testes...
********* Start testing of Tst_serialport *********
Config: Using QtTest library 5.15.8, Qt 5.15.8 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 12.2.1 20230201), arch unknown
PASS : Tst_serialport::initTestCase()
2023/02/15 11:23:40 socat[6248] N PTY is /dev/pts/2
2023/02/15 11:23:40 socat[6248] N PTY is /dev/pts/3
2023/02/15 11:23:40 socat[6248] N starting data transfer loop with FDs [5,5] and [7,7]
PASS : Tst_serialport::sanityCheck()
FAIL! : Tst_serialport::checkSendMessage() Compared values are not the same
Actual (_store->lastMessage): ""
Expected ("Hello") : Hello
Loc: [../VolanteAlphaQT_1/test/tst_serialport.cpp(35)]
PASS : Tst_serialport::closeHandle()
PASS : Tst_serialport::cleanupTestCase()
Totals: 4 passed, 1 failed, 0 skipped, 0 blacklisted, 1005ms
********* Finished testing of Tst_serialport *********
11:23:41: /home/micron/sav/Trabalhos/2022-2023/FormulaStudent/VolanteAlphaQT/build-VolanteAlphaQT-Desktop-Testing/bin/VolanteAlphaQT_testes exited with code 1
As usual all per most of my questions its not very descriptive it basically just never triggers the signal ReadyRead which in turn causes last message to be blank
Conclusion / TL;DR
So what am i doing wrong? why is the ready read signal not being triggered? Is there a better way to simulate/mock a serial connection?
Well, I found the solution.
Apparently it wasn't a socat problem, the ready signal is way slower than I had in mind and when I slept it actually froze the process. Due to the ready signal taking some time even after the buffer itself being ready, the QCOMPARE came right after the "unfreeze" making the stall useless.
The actual solution was rather simple I placed a _store->waitForReadyRead(); so I could wait for the signal to be sent without freezing the process.

Unix socket hangs on recv, until I place/remove a breakpoint anywhere

[TL;DR version: the code below hangs indefinitely on the second recv() call both in Release and Debug mode. In Debug, if I place or remove a breakpoint anywhere in the code, it makes the execution continue and everything behaves normally]
I'm coding a simple client-server communication using UNIX sockets. The server is in C++ while the client is in python. The connection (TCP socket on localhost) gets established no problem, but when it comes to receiving data on the server side, it hangs on the recv function. Here is the code where the problem happens:
bool server::readBody(int csock) // csock is the socket filedescriptor
{
int bytecount;
// protobuf-related variables
google::protobuf::uint32 siz;
kinMsg::request message;
// if the code is working, client will send false
// I initialize at true to be sure that the message is actually read
message.set_endconnection(true);
// First, read 4-characters header for extracting data size
char buffer_hdr[5];
if((bytecount = recv(csock, buffer_hdr, 4, MSG_WAITALL))== -1)
::std::cerr << "Error receiving data "<< ::std::endl;
buffer_hdr[4] = '\0';
siz = atoi(buffer_hdr);
// Second, read the data. The code hangs here !!
char buffer [siz];
if((bytecount = recv(csock, (void *)buffer, siz, MSG_WAITALL))== -1)
::std::cerr << "Error receiving data " << errno << ::std::endl;
//Finally, process the protobuf message
google::protobuf::io::ArrayInputStream ais(buffer,siz);
google::protobuf::io::CodedInputStream coded_input(&ais);
google::protobuf::io::CodedInputStream::Limit msgLimit = coded_input.PushLimit(siz);
message.ParseFromCodedStream(&coded_input);
coded_input.PopLimit(msgLimit);
if (message.has_endconnection())
return !message.endconnection();
return false;
}
As can be seen in the code, the protocol is such that the client will first send the number of bytes in the message in a 4-character array, followed by the protobuf message itself. The first recv call works well and does not hang. Then, the code hangs on the second recv call, which should be recovering the body of the message.
Now, for the interesting part. When run in Release mode, the code hangs indefinitely and I have to kill either the client or the server. It does not matter whether I run it from my IDE (qtcreator), or from the CLI after a clean build (using cmake/g++).
When I run the code in Debug mode, it also hangs at the same recv() call. Then, if I place or remove a breakpoint ANYWHERE in the code (before or after that line of code), it starts again and works perfectly : the server receives the data, and reads the correct message.endconnection() value before returning out of the readBody function. The breakpoint that I have to place to trigger this behavior is not necessarily trigerred. Since the readBody() function is in a loop (my C++ server waits for requests from the python client), at the next iteration, the same behavior happens again, and I have to place or remove a breakpoint anywhere in the code, which is not necessarily triggered, in order to go past that recv() call. The loop looks like this:
bool connection = true;
// server waiting for client connection
if (!waitForConnection(connectionID)) std::cerr << "Error accepting connection" << ::std::endl;
// main loop
while(connection)
{
if((bytecount = recv(connectionID, buffer, 4, MSG_PEEK))== -1)
{
::std::cerr << "Error receiving data "<< ::std::endl;
}
else if (bytecount == 0)
break;
try
{
if(readBody(connectionID))
{
sendResponse(connectionID);
}
// if client is requesting disconnection, break the while(true)
else
{
std::cout << "Disconnection requested by client. Exiting ..." << std::endl;
connection = false;
}
}
catch(...)
{
std::cerr << "Erro receiving message from client" << std::endl;
}
}
Finally, as you can see, when the program returns from readBody(), it sends back another message to the client, which processes it and prints in the standard output (python code working, not shown because the question is already long enough). From this last behavior, I can conclude that the protocol and client code are OK. I tried to put sleep instructions at many points to see whether it was a timing problem, but it did not change anything.
I searched all over Google and SO for a similar problem, but did not find anything. Help would be much appreciated !
The solution is to not use any flags. Call recv with 0 for the flags or just use read instead of recv.
You are requesting the socket for data that is not there. The recv expects 10 bytes, but the client only sent 6. The MSG_WAITALL states clearly that the call should block until 10 bytes are available in the stream.
If you dont use any flags, the call will succeed with a bytecount at 6, which is the exact same effect than with MSG_DONTWAIT, without the potential side effects of non-blocking calls.
I did the test on the github project, it works.
The solution is to replace MSG_WAITALL by MSG_DONTWAIT in the recv() calls. It now works fine. To summarize, it makes the recv() calls non blocking, which makes the whole code work fine.
However, this still raises many questions, the first of which being: why was it working with this weird breakpoint changing thing ?
If the socket was blocking in the first place, one could assume that it is because there is no data on the socket. Let's assume both situations here :
There is no data on the socket, which is the reason why the blocking recv() call was not working. Changing it to a non blocking recv() call would then, in the same situation, trigger an error. If not, the protobuf deserialization would afterwards fail trying to deserialize from an empty buffer. But it does not ...
There is data on the socket. Then, why on earth would it block in the first place ?
Obviously there is something that I don't get about sockets in C, and I'd be very happy if somebody has an explanation for this behavior !

Multithreading in C++, receive message from socket

I have studied Java for 8 months but decided to learn some c++ to on my spare time.
I'm currently making a multithreaded server in QT with minGW. My problem is that when a client connects, I create an instance of Client( which is a class) and pass the socket in the client class contructor.
And then I start a thread in the client object (startClient()) which is going to wait for messages, but it doesn't. Btw, startClient is a method that I create a thread from. See code below.
What happens then? Yes, when I try to send messages to the server, only errors, the server won't print out that a new client connects, and for some reason my computer starts working really hard. And qtcreator gets super slow until I close the server-program.
What I actually is trying to achieve is an object which derives the thread, but I have heard that it isn't a very good idea to do so in C++.
The listener loop in the server:
for (;;)
{
if ((sock_CONNECTION = accept(sock_LISTEN, (SOCKADDR*)&ADDRESS, &AddressSize)))
{
cout << "\nClient connected" << endl;
Client client(sock_CONNECTION); // new object and pass the socket
std::thread t1(&Client::startClient, client); //create thread of the method
t1.detach();
}
}
the Client class:
Client::Client(SOCKET socket)
{
this->socket = socket;
cout << "hello from clientconstructor ! " << endl;
}
void Client::startClient()
{
cout << "hello from clientmethod ! " << endl;
// WHEN I ADD THE CODE BELOW I DON'T GET ANY OUTPUT ON THE CONSOLE!
// No messages gets received either.
char RecvdData[100] = "";
int ret;
for(;;)
{
try
{
ret = recv(socket,RecvdData,sizeof(RecvdData),0);
cout << RecvdData << endl;
}
catch (int e)
{
cout << "Error sending message to client" << endl;
}
}
}
It looks like your Client object is going out of scope after you detach it.
if (/* ... */)
{
Client client(sock_CONNECTION);
std::thread t1(&Client::startClient, client);
t1.detach();
} // GOING OUT OF SCOPE HERE
You'll need to create a pointer of your client object and manage it, or define it at a higher level where it won't go out of scope.
The fact that you never see any output from the Server likely means that your client is unable to connect to your Server in the first place. Check that you are doing your IP addressing correctly in your connect calls. If that looks good, then maybe there is a firewall blocking the connection. Turn that off or open the necessary ports.
Your connecting client is likely getting an error from connect that it is interpreting as success and then trying to send lots of traffic on an invalid socket as fast as it can, which is why your machine seems to be working hard.
You definitely need to check the return values from accept, connect, read and write more carefully. Also, make sure that you aren't running your Server's accept socket in non-blocking mode. I don't think that you are because you aren't seeing any output, but if you did it would infinitely loop on error spawning tons of threads that would also infinitely loop on errors and likely bring your machine to its knees.
If I misunderstood what is happening and you do actually get a client connection and have "Client connected" and "hello from client method ! " output, then it is highly likely that your calls to recv() are failing and you are ignoring the failure. So, you are in a tight infinite loop that is repeatedly outputting "" as fast as possible.
You also probably want to change your catch block to catch (...) rather than int. I doubt either recv() or cout throw an int. Even so, that catch block won't be invoked when recv fails because recv doesn't throw any exceptions AFAIK. It returns its failure indicator through its return value.

C++ Server - Client Message Sync

I writing a small program that can Send File from Client -> Server (Send) and Server -> Client(Request).
Well done this part but the problems comes when:
1. I found the File on Server, How can I execute a cin on the client side?
2. How can I force my messages between Server and Client to be synced? I mean I dont want the Server to move to next step or freeze on the receive.
For Example(No Threading applied in this porblem):-
Server: Waiting a Message from Client.
Client: Send the Message.
Client: Waiting a Message from Client.
Server: Send the Message.
.....etc.
In a rare times the messages arrive on order but 99.999% of the time they don't and the program on two sides freeze.
The problem with the inorder messages was a thread on the client side who kept reading the inc replies without allowing the actual functions to see them.
However, about point 1.
I am trying in this code:
1. No shared resources so i am trying to define everything inside this function (part of it where the problem happening)
2. I was trying to pass this function to a thread so the server can accept more clients.
3. send & receive nothing special about them just a normal send/recv calls.
3. Question: if SendMyMessage & ReceiveMyMessage is going to be used by different threads, should I pass the socket to them with the message?
void ExecuteRequest(void * x)
{
RequestInfo * req = (RequestInfo *) x;
// 1st Message Direction get or put
fstream myFile;
myFile.open(req->_fName);
char tmp;
string _MSG= "";
string cFile = "*";
if(req->_fDir.compare("put") == 0)
{
if(myFile.is_open())
{
SendMyMessage("*F*");
cFile = ReceiveMyMessage();
// I want here to ask the client what to do after he found the that file exist on the server,
// I want the client to to get a message "*F*", then a cin command appear to him
// then the client enter a char
// then a message sent back to the server
// then the server continue executing the code
//More code
}
Client side:
{
cout <<"Waiting Message" <<endl;
temps = ReceiveMessage();
if(temps.compare("*F*") == 0)
{
cout <<"File found on Server want to:\n(1)Replace it.\n(2)Append to it." <<endl;
cin>>temps;
SendMyMessage(temps);
}}
I am using visual studio 2013
Windowx 7
thread am using: _beginthread (I removed all threads)
Regards,
On linux, there is a system call "select" using which the server can wait on the open sockets. As soon as there is an activity, like client wrote something, the server wakes up on that sockets and processes the data.
You are on windows platform. So :
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx

Presenting sent and received chat messages in "order" for both the client and server

I have a simple (very simple:) ) client and server which can send text messages over TCP, It's flawed because I don't know how to listen to the messages and print them on the screen as well as send messages at the same time (for both client and server).
Also I have difficulty in presenting all the sent and received messages between the client and server in the order the messages were sent.
For example on the server side the chat may look like this
Server:Hi there
Client:Hi
And on the client side the same chat looks like this
Client:Hi
Server:Hi there
The messages are in different order and both users see differently. My main question is, how would I go about synchronizing the output so that they both see the same thing?
Keeping in mind what I mentioned earlier about not knowing how to listen and send simultaneously, this is the message loop for the sever and client.
Server message loop
while(true){
cout<<"-[SERVER]: ";
getline(cin,send_text);
if (sizeof(send_text) > 0 ){
bytes_out = send(client,send_text.c_str(),send_text.length()+1,0);
cout<< endl;
if (bytes_out == SOCKET_ERROR){
cout<<"-[SERVER error in sending.]" << endl;
break;
}
}
bytes_in = recv(client,recvd_text,sizeof(recvd_text),0);
if (bytes_in > 0 ){
cout<<"-[CLIENT]: " << recvd_text << endl; //output on screen
}
if (bytes_in == 0){
cout<<"-[CLIENT has disconnected.]" << endl;
break;
}
if (bytes_in == SOCKET_ERROR){
cout<<"-[CLIENT closed unexpectedly.]" << endl;
break;
}
}
Client message loop
while (true){
cout<<"-[CLIENT]: ";
getline(cin,send_text);
if(sizeof(send_text) > 0){
bytes_out = send(con_sock,send_text.c_str(),send_text.length()+1,0);
if (bytes_out == SOCKET_ERROR){
cout<<"-[CLIENT error in sending.]" << endl;
break;
}
}
bytes_in = recv(con_sock,recvd_text,sizeof(recvd_text),0);
if (bytes_in > 0){
cout<<"-[SERVER]: " << recvd_text << endl;
}
if (bytes_in == 0){
cout<<"-[Server has disconnected." << endl;
break;
}
if (bytes_in == SOCKET_ERROR){
cout<<"-[Server closed unexpectedly." << endl;
break;
}
}
return true;
The core problem is how to wait for incoming messages and for user input at the same time. (Once you'll be able to do it, the "synchronization" will follow naturally, since messages will be displayed as they are sent or received).
The solution to this problem is using select. select can wait for input on several file handles (e.g. standard input and a socket) and return when there's data available. You can then handle the data: if it's from the socket, display it. If it's from the user, send it to the remote host.
Here's an example chat client/server program using select. (The example is in Python not C++, but the principle is the same).
Windows-specific
In Windows, select() is provided by the Winsock library and only works on sockets. To wait for input from the console and from a network socket, it looks like you will need to use a combination of WaitForMultipleObjects, GetStdHandle and WSAEventSelect. In Unix-like environments it's much simpler because the standard input and sockets are all file descriptors.
A simpler solution in Windows would be a message-passing based one. Use a window for the text input, and use WSAAsyncSelect to get a message when network input is ready.
In some sense, this is a question about internet protocols. Most application protocols would solve this by including a kind of acknowledgment response when the message successfully reaches its definition. Such a communication might look something like this:
Server sends some kind of header identifying a chat message, with the contents "Hi there".
Client receives chat message, and replies with a different header indicating acknowledgment.
Server receives the client's acknowledgment, and then prints the message to the screen.
The operating system technically already does this as part of TCP, but this is probably the easiest way to accomplish something similar at the application level.