qt 线程中接收socket数据

#ifndef TCP_THREAD_H
#define TCP_THREAD_H

#include
#include
#include

#define MAX_SEND_MSG_LEN 68

struct _loop_buf {
int num_of_unit; // Number of data units
int unit_size;
int rhead; // Head for read
int whead; // Head for write
void *buf_head;
};

class TcpThread : public QThread
{
Q_OBJECT

private:
QTcpServer *tcpServer;
QTcpSocket *socket;
QString ipAddress;
quint16 destinationPort;
int Flag;
bool quit;
struct _loop_buf loop_buf;

void run() Q_DECL_OVERRIDE;
void processMessage(char *msg);

int init_loop_buf(struct _loop_buf *loop_buf, int num_of_unit, int unit_size);
void reset_loop_buf(struct _loop_buf *loop_buf);
void release_loop_buf(struct _loop_buf *loop_buf);
int read_data_from_loop_buf(struct _loop_buf *loop_buf, void *data_unit);    

QByteArray bytes;
QByteArray byteGet;

public:
TcpThread(QString ipAddress, quint16 destinationPort, QObject *parent = 0);
~TcpThread();
int addMessage(void *data_unit);

signals:
void error(int socketError, const QString &message);

public slots:
void finishWork(void);
void newConnectionSlot();
void dataReceived();
};

#endif // TCP_THREAD_H
.h文件


#if defined(_MSC_VER) && (_MSC_VER >= 1600)
#pragma execution_character_set("utf-8")
#endif

//#define MAX_SEND_MSG_LEN = 68
#include "TcpThread.h"
#include "widget.h"
#include <QDebug>


TcpThread::TcpThread(QString ipAddress, quint16 destinationPort, QObject *parent)
    : QThread(parent), quit(false)
{
    this->ipAddress = ipAddress;
    this->destinationPort = destinationPort;

    // Initialize loop buffer
    // Max length of messages to be sent is 68 bytes.
    if (init_loop_buf(&loop_buf, 128000, MAX_SEND_MSG_LEN) != 0) {
        qDebug() << "Can't initialize loop buffer.";
        return;
    }
}

TcpThread::~TcpThread()
{
    // Wait for the end of the thread.
    quit = true;
    wait();
}

void TcpThread::run()
{
    //
    // At here, it is in the execution context of newly created thread.
    // So, it is better to define or create objects here.
    // Or, following error may occurred:
    //     QObject: Cannot create children for a parent that is in a different thread
    //
    char *msg;//, *sendMsg;
    int conn_timeout = 30000;
    int read_timeout = 5000;
    int write_timeout = 5000;

    int bytesToRead, readBytes;
    int bytesToWrite, writeBytes;
    int ret;
    int gotMessageHead = 0;
    int toGetNewMessage = 0;

    //msg = (char *)calloc(65536 + 128, 1);
    msg = (char *)calloc(MAX_SEND_MSG_LEN, 1);
    if (msg == NULL) {
        qDebug() << "Can't allocate memory.";
        return;
    }

    tcpServer = new QTcpServer();
    socket = new QTcpSocket();
    //connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()), Qt::DirectConnection);


    if (!tcpServer->isListening())
    {
        qDebug() << ipAddress;
        //if (tcpServer->listen(QHostAddress::QHostAddress(ipAddress), 16512))
        if (tcpServer->listen(QHostAddress::Any, 16512))
        {
            //m_pEdt_Info->append(QObject::tr("打开监听端口成功!111"));
            qDebug()<< QObject::tr("打开监听端口成功!111");
            socket = tcpServer->nextPendingConnection();
//            //connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
            connect(socket, SIGNAL(readyRead()),this, SLOT(dataReceived()));

        }
        else
        {
            //m_pEdt_Info->append(QObject::tr("打开监听端口失败!"));
            qDebug()<< QObject::tr("打开监听端口失败!11");
        }
    }
    else
    {
        //m_pEdt_Info->append(QObject::tr("正在监听中...!"));
        qDebug()<< QObject::tr("正在监听中...!");

    }


        qDebug() << "Connected to" << ipAddress;


        // reset read variables
        readBytes = 0;
        bytesToRead = 4;
        gotMessageHead = 0;

        // reset write variables
        writeBytes = 0;
        toGetNewMessage = 1;


}

void TcpThread::processMessage(char *msg)
{
    qDebug() << "Receive message:" << *(unsigned short *)msg <<
            ". Length:" << *(unsigned short *)(msg + 2);
}

void TcpThread::finishWork(void)
{
    quit = true;
}

int TcpThread::init_loop_buf(struct _loop_buf *loop_buf, int num_of_unit, int unit_size)
{
    unsigned long long total_size;

    total_size = (unsigned long long)unit_size * (unsigned long long)num_of_unit;
    if (total_size > 0x7fffffff) {
        printf("Memory to be allocated is too large.\n");
        return -1;
    }

    if (num_of_unit > 0x7ffffff0) {
        printf("Buffer size can't exceed 0x7ffffff0.\n");
        return -1;
    }

    loop_buf->num_of_unit = num_of_unit;
    loop_buf->unit_size = unit_size;
    loop_buf->rhead = 0;
    loop_buf->whead = 0;
    loop_buf->buf_head = malloc(total_size);

    if (loop_buf->buf_head == NULL) {
        printf("Can't allocate memory for the loop buffer.\n");
        return -1;
    }

    return 0;
}

// Be careful to call this function. You must make sure that
// nobody is using the loop buffer pointed by 'loop_buf',
// or error may occur.
void TcpThread::reset_loop_buf(struct _loop_buf *loop_buf)
{
    loop_buf->rhead = 0;
    loop_buf->whead = 0;
}

void TcpThread::release_loop_buf(struct _loop_buf *loop_buf)
{
    free(loop_buf->buf_head);
}

//
// Return value:
//     0: Success.
//    -1: The loop buffer is NULL.
//
int TcpThread::read_data_from_loop_buf(struct _loop_buf *loop_buf, void *data_unit)
{
    if (loop_buf->rhead == loop_buf->whead) {
        // The buffer is null.
        return -1;
    }

    //
    // Do your work here, you can read data from the loop buffer.
    // Following is just an example.
    //
    // Note:
    //     Must copy the data out, or the content of the data unit may be
    //     overwritten.
    //
    memcpy(data_unit, (char *)loop_buf->buf_head + loop_buf->rhead * loop_buf->unit_size, (size_t)loop_buf->unit_size);

    if (loop_buf->rhead == (loop_buf->num_of_unit - 1)) {
        loop_buf->rhead = 0;
    } else {
        loop_buf->rhead++;
    }

    return 0;
}

//
//     --- IMPORTANT ---
// There is no mutex to avoid race condition in the function's implementation.
// So, to call this function from only one code source.
//
//Return value:
//    0: Success.
//   -1: The loop buffer is full.
//
int TcpThread::addMessage(void *data_unit)
{
    int tmp_whead = 0;

    tmp_whead = loop_buf.whead + 1;
    if (tmp_whead >= loop_buf.num_of_unit) {
        tmp_whead = 0;
    }

    if (tmp_whead == loop_buf.rhead) {
        // The buffer is full.
        return -1;
    }

    //
    // Do your work here, you can write data to the loop buffer.
    // Following is just an example.
    //
    memcpy((char *)loop_buf.buf_head + loop_buf.whead * loop_buf.unit_size, data_unit, (size_t)loop_buf.unit_size);

    loop_buf.whead = tmp_whead;

    return 0;
}

void TcpThread::newConnectionSlot()
{
    //m_pEdt_Info->append(QObject::tr("有新客户端连接到服务器"));
    socket = tcpServer->nextPendingConnection();
    connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
    connect(socket, SIGNAL(readyRead()),this, SLOT(dataReceived()));
}

void TcpThread::dataReceived()
{
    bytes = socket->readAll();
    qDebug() << bytes.length() << bytes.size();
    //if (bytes.size()=0) waitfo
    if (byteGet.size()!=0){
        byteGet.append(bytes.left(68-byteGet.size()));
        bytes.remove(0,68-byteGet.size());
        qDebug() << byteGet.length() << bytes.size();
    }
    for (;bytes.size()>=68;){
        byteGet = bytes.left(68);
        //m_pEdt_Info->append(byteGet.toHex());
        bytes.remove(0,68);
        qDebug() << byteGet.length() << bytes.size();
    }
    if (bytes.size()>0&&bytes.size()<68){
        byteGet = bytes;
        bytes.remove(0,byteGet.size());
        qDebug() << byteGet.toHex();
        qDebug() << byteGet.length() << bytes.size();
        //bytes = m_pSocket->readLine();
        //m_pServer->close();
    }
}

.cpp文件
线程中接收数据,使用信号机制可不可以啊?
我用connect(socket, SIGNAL(readyRead()),this, SLOT(dataReceived()));
发现Slot里面定义的接收数据并未调用到。为什么,是this的问题,还是不应该这样使用信号机制。或者还有别的什么好方法吗,麻烦各位大神热点,感激

2个回答

贴一下你的socket所属的类(包括.h和.cpp)

qq423399099
小灸舞 回复tmaolein: 检查connect的返回值,看是不是true,如果是true的话看我下面的回复
4 年多之前 回复
tmaolein
tmaolein 主要就是dataReceive什么也没显示
4 年多之前 回复
tmaolein
tmaolein .h文件
4 年多之前 回复

手册中原文:
This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.

readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

Note for developers implementing classes derived from QIODevice: you should always emit readyRead() when new data has arrived (do not emit it only because there's data still to be read in your buffers). Do not emit readyRead() in other conditions.

你看一下tcpsocket的状态是否是error啊。
手册中是这么说的:
This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.
意思是readyread信号在且只在有新数据到达时才会被发射。需要注意的是readyread并不是递归的(readyRead() is not emitted recursively)。
所以在收到新数据的时候只要你没有解除链接,那么这个就一直存在,除非socket状态编程error或者closingstatus等特殊状态。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐