Simple TCP Server failure.
-
Hi, I'm little confused by qt events. I'm writing simple chat server and client. Somehow, I'm getting SIGSEGV signal on qDebug() or "double free or corruption" on unknown function (it shows only disassembled code). Can anyone explain me what I'm doing wrong? also, it is console based application.
Regards.
[code]#define chunk_size 1024
...
void TcpSocket::client_readyRead()
{
// client data available.
qDebug() << this->bytesAvailable() << "bytes available from" << this->socketDescriptor();// get data size. if(!this->blockSize) { if((quint64)this->bytesAvailable() < sizeof(quint64)) return; else this->read((char *)&this->blockSize, sizeof(quint64)); } if(this->blockSize) { // we got data to read. qDebug() << "expecting" << this->blockSize << "bytes to read."; // it crashes here. type of blockSize is quint64 int data_size; if(this->blockSize != chunk_size) data_size = this->blockSize % chunk_size; else data_size = this->blockSize; char temp[data_size]; qint64 received = this->read(temp, data_size); if(received < 0) { // error receiving data. qDebug() << "error receiving data from" << this->socketDescriptor(); this->blockSize = 0; return; } else { if(received) { qDebug() << "received" << received << "bytes from" << this->socketDescriptor(); this->blockSize -= received; this->chunkArray.append(temp, received); if(!this->blockSize) { qDebug() << this->chunkArray; //emit dataReady(this->chunkArray); } } } }
}[/code]
sending part is like this:
[code]int client_send(int sockfd, const char *data, unsigned long long datalen)
{
unsigned long long newlen = datalen + sizeof(unsigned long long);
int offset = 0;
char temp[newlen];
memmove(temp, (char )&datalen, sizeof(unsigned long long));
memmove(temp + sizeof(unsigned long long), data, datalen);
while(newlen)
{
int data_size = 0;
if(newlen != chunk_size)
data_size = newlen % chunk_size;
else
data_size = chunk_size;
int sent = send(sockfd, temp + offset, data_size, 0);
if(sent != -1)
{
if(sent)
{
offset += sent;
newlen -= sent;
}
}
else
{
newlen = 0;
offset = 0;
}
}
return offset;
}
...
int main(int argc, char argv[])
{
client_send(sockfd, "hello ", 6);
client_send(sockfd, "world ", 6);
client_send(sockfd, "this ", 5);
client_send(sockfd, "is ", 3);
client_send(sockfd, "test", 4);
return 0;
}[/code] -
However, it was fixed by connecting signals with Qt::QueuedConnection, I don't understand why, but it is not getting all data, sometimes it does, sometimes it not. Because, when I send a lot of requests, readyRead slot is triggered only once instead of 5 times (amount of send requests). As I said, it works sometimes and sometimes not, but why?
Regards.
EDIT: log shows output like this:
[code]64 bytes available from 7
expecting 6 bytes to read.
received 6 bytes from 7
"hello " [/code]sometimes like this:
[code]23 bytes available from 7
expecting 3 bytes to read.
received 3 bytes from 7
"hello world this is " [/code]and like this:
[code]12 bytes available from 7
expecting 4 bytes to read.
received 4 bytes from 7
"hello world this is test" [/code]and so on.. the data I'm sending for each client_send function is sent successfully, but not all the data is received.. why? :-(
-
Your sending application is apparently not based on Qt.
For some tests it might be better to use Qt's Network examples. There is the "fortune client":http://qt-project.org/doc/qt-5.0/qtnetwork/fortuneclient.html and the "fortune server":http://qt-project.org/doc/qt-5.0/qtnetwork/fortuneserver.html as a complete set for TCP/IP communication.Hope that helps.
-
I've already seen fortune server and client example, but it uses QDataStream for transfer data, which I'm not using. Imagine instead of client_send, I'm using custom QTcpSocket::write method (which modifies first 8 bytes to size of data to be sent and then actual data).
However, output must be like this for each client_send function, but I really don't get how to make this happen.
[code]hello
world
this
is
test[/code]EDIT: I have solved it by modifying this piece of code, but I'm interested if this way is safe.
[code]if(!this->blockSize)
{
qDebug() << this->chunkArray;
//emit dataReady(this->chunkArray);
this->chunkArray.clear();
if(this->bytesAvailable())
emit readyRead(); // <-- is this way safe?
}[/code]Regards.
-
I am using QTcpClient without QDataStream and without problems.
However, your sending application does not have an event loop as both the fortune server and fortune client have. AFAIK that is the reason that your application does not send all the stuff (assuming that your sending app is also using QTcpClient). -
Please check my previous edited post.
Regards. -
Just saw that you have edited your last post.
Your receiving part might receive the incoming data byte by byte. Typically your application may be triggered by a readyRead signal and able to read all information, but all has been introduced to the buffer yet. -
You mean it could read same data twice or more and append to buffer which will cause false results?
EDIT: should I use QMetaObject::invokeMethod() instead? -
[quote author="Overflowz" date="1371142820"]You mean it could read same data twice or more and append to buffer which will cause false results?[/quote]
My assumption that client_readyRead is triggered by QTcpSocket signal readyRead, so it might be triggered several times.Nevertheless, you did not disclose yet, what kind of application you are using for sending. If this is using QTcpSocket communication, I am wondering if this can work, but may be. Or there is much more around than you show. At the main.cpp does not set up an event loop.
In case QTcpSocket is used for sending and when this is possible without event loop, you might exit the program before all stuff has been send.Again my suggestion would be to strip down the fortune examples to what you need. This is probably the easier start for you to work the issues out.
-
Thanks for reply, I understood that but sender part is just C application, with non-blocking sockets (AFAIK QTcpSocket uses non-blocking sockets too) which as I guess will give same results.
-
QTcpSocket is non-blocking.
However, are you sure that the stuff is being sent by your application before it closes? I might well be that the application is writing to buffers and it closes before the buffers have been emptied. If that is the case, it would completely explain the issues you have. -
as I said in previous post, I fixed it by modifying that piece of code which I posted above. I'm 100% sure that data is sent successfully, because of bytesAvailable() returns count of whole data length (I'll add error checking too, but for my debugging it's not important, I'm checking it from debugger).
Regards.
-
Bumping this thread.
Apologies.