QTcpSocket有时候无法发送数据

6
我有两个QT应用程序。其中一个应用程序可以被认为是持有大量数据的,每秒向第二个应用程序发送约10KB的数据块。
早先我尝试使用QUdpSocket来传输数据,但由于MTU限制约为2-5K,需要自己分割和重组数据,所以我转而使用了QTcpSocket。
有时候使用QTcpSocket可以正确地发送数据(特别是如果我非常频繁地写入数据,大约每100毫秒一次),但有时候根本没有发送数据。即使过了5秒钟也没有。有时几个数据块会在内部缓冲长时间(几秒钟),然后一起发送。
m_socket = new QTcpSocket(this);
m_socket->connectToHost(QHostAddress::LocalHost, 45454);

sendDataEverySec()
{
    QByteArray datagram(10000, 'a');
    qint64 len = m_socket->write(datagram);
    if(len != datagram.size())
           qDebug() << "Error"; //this NEVER occurs in MY case.
    m_socket->flush();
}

在接收端,我使用readyRead信号来知道何时到达数据。
如何确保数据立即发送?有没有更好的替代方案?
编辑:当我间隔1秒钟后再写入时,每次发送者发送数据时,我在接收端都会收到"QAbstractSocket::SocketTimeoutError"。如果发送者频繁写入数据,则不会收到此错误。 按照我正在尝试的方式使用QTcpSocket流传输数据是否可以?
编辑2:在接收端,当发出readyRead信号时,我再次检查了while(m_socket->waitForReadyRead(500)),由于这个检查而导致了"QAbstractSocket::SocketTimeoutError"。同时,这个检查也阻止了单个块的传递。 经过更多的文档阅读,似乎readyRead将在新数据可用时持续发出,因此不需要waitForReadyRead。 我已经接收到所有发送的数据,但是数据并不会立即到达。有时两三个块会合并。这可能是由于接收端延迟读取数据等原因造成的。

你可以尝试在setSocketOption API中设置QAbstractSocket :: LowDelayOption标志吗? - Kunal
@Kunal,我尝试了LowDelayOption和KeepAliveOption,但都没有成功。有趣的是,一旦发送方发送数据,接收方就会显示“QAbstractSocket :: SocketTimeoutError”。这发生在每隔1秒写入数据时。 - vivek.m
我相信问题出在接收端。请展示一下你如何处理传入连接。 - Chris Browet
2个回答

2
在接收端,当发出readyRead信号时,我再次检查while(m_socket->waitForReadyRead(500)),结果出现了"QAbstractSocket::SocketTimeoutError"。同时,这个检查还阻止了单个数据块的传递。
阅读更多文档后,似乎只要有新数据可用,readyRead信号就会不断地发出,所以不需要使用waitForReadyRead了。这解决了我的问题。

0

我的客户端服务器应用程序的典型解决方案。

在服务器端:

class Server: public QTcpServer {

public:
    Server(QObject *parent = 0);
    ~Server();
private slots:
    void readyRead();
    void disconnected();
protected:
    void incomingConnection(int);

};

关于C++:

void Server::incomingConnection(int socketfd) {

    QTcpSocket *client = new QTcpSocket(this);
    client->setSocketDescriptor(socketfd);


    connect(client, SIGNAL(readyRead()), this, SLOT(readyRead()));
    connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));
}

void Server::disconnected() {
    QTcpSocket *client = (QTcpSocket*) sender();

    qDebug() << " INFO : " << QDateTime::currentDateTime()
            << " : CLIENT DISCONNECTED " << client->peerAddress().toString();
}

void Server::readyRead() {
    QTcpSocket *client = (QTcpSocket*) sender();

    while (client->canReadLine()) {
              //here i needed a string..
        QString line = QString::fromUtf8(client->readLine()).trimmed(); 
    }
}

在客户端:
类 Client:公共 QTcpSocket {
public:
    Client(const QHostAddress&, int, QObject* = 0);
    ~Client();
    void Client::sendMessage(const QString& );
private slots:
    void readyRead();
    void connected();
public slots:
    void doConnect();
};

关于C++:

void Client::readyRead() {

    // if you need to read the answer of server..
    while (this->canReadLine()) {
    }
}

void Client::doConnect() {
    this->connectToHost(ip_, port_);
    qDebug() << " INFO : " << QDateTime::currentDateTime()
            << " : CONNESSIONE...";
}

void Client::connected() {
    qDebug() << " INFO : " << QDateTime::currentDateTime() << " : CONNESSO a "
            << ip_ << " e PORTA " << port_;
    //do stuff if you need
}


void Client::sendMessage(const QString& message) {
    this->write(message.toUtf8());
    this->write("\n"); //every message ends with a new line
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接