2012-03-15 27 views
6

Tengo dos aplicaciones QT. Se puede considerar que una aplicación contiene un gran dato y envía aproximadamente 10 KB de fragmento de datos por segundo a segunda aplicación.QTcpSocket no envía datos a veces

Anteriormente traté de usar QUdpSocket para transmitir los datos, pero debido a la limitación de MTU de aproximadamente 2-5K y necesito dividir y reunir los datos, cambié a QTcpSocket.

A veces los datos se envían correctamente con QTcpSocket (especialmente si escribo datos con mucha frecuencia ~ cada 100 ms) pero a veces los datos no se envían en absoluto. Ni siquiera después de 5 seg. Y, a veces, varios fragmentos de datos se almacenan en el búfer interno durante un largo período (varios segundos) y luego se envían juntos.

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(); 
} 

En el lado receptor, utilizo readyRead señal para saber cuándo ha llegado datos.

¿Cómo puedo garantizar que los datos se envíen inmediatamente? ¿Hay alguna alternativa mejor para lo que estoy tratando de hacer?

Editar :: Cuando escribo después de largas brechas de 1 segundo, recibo "QAbstractSocket::SocketTimeoutError" en el lado del receptor cada vez que el remitente envía datos. Este error no se recibe si el remitente escribe datos con frecuencia.
¿Está bien utilizar QTcpSocket para transmitir datos de la manera en que lo estoy haciendo?

Edición 2: En el lado del receptor, cuando se emite la señal readyRead, nuevamente estaba revisando while(m_socket->waitForReadyRead(500)) y estaba obteniendo "QAbstractSocket::SocketTimeoutError" debido a esto. Además, este control impedía la entrega de trozos individuales.
Después de revisar más documentos, parece que readyRead se emitirá continuamente cuando haya nuevos datos disponibles, por lo que no es necesario waitForReadyRead.
Recibo todos los datos enviados, pero aún así los datos no se reciben de inmediato. A veces se combinan dos o tres fragmentos. Esto puede deberse a un retraso en el lado del receptor al leer datos, etc.

+0

¿Puedes intentar configurar el indicador QAbstractSocket :: LowDelayOption para setSocketOption API? – Kunal

+0

@Kunal, probé LowDelayOption y KeepAliveOption sin ningún éxito.Curiosamente, tan pronto como el remitente envía datos, el receptor muestra un "QAbstractSocket :: SocketTimeoutError". Esto sucede al escribir datos en espacios de 1 segundo. –

+0

Estoy convencido de que el problema está en el lado receptor. Por favor, muéstranos cómo manejas las conexiones entrantes. – Koying

Respuesta

2

En el lado receptor, cuando se emite la señal de readyRead, estaba de nuevo comprobando while(m_socket->waitForReadyRead(500)) y que estaba recibiendo "QAbstractSocket::SocketTimeoutError" debido a esto. Además, este control impedía la entrega de trozos individuales.

Después de revisar los documentos, parece que Ready Read se emitirá continuamente cuando haya nuevos datos disponibles, por lo que no es necesario waitForReadyRead. Había solucionado mi problema.

0

mi solución típica para la aplicación de servidor cliente.

en el lado del servidor:

class Server: public QTcpServer { 

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

}; 

de CPP:

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(); 
    } 
} 

en el cliente:

clase Cliente: QTcpSocket pública {

public: 
    Client(const QHostAddress&, int, QObject* = 0); 
    ~Client(); 
    void Client::sendMessage(const QString&); 
private slots: 
    void readyRead(); 
    void connected(); 
public slots: 
    void doConnect(); 
}; 

de CPP:

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 
} 
Cuestiones relacionadas