2012-03-15 35 views
6

Tôi có hai ứng dụng QT. Một ứng dụng có thể được coi là giữ một dữ liệu lớn và nó gửi khoảng 10 KB dữ liệu chunk mỗi giây đến ứng dụng thứ hai. Trước đó, tôi đã thử sử dụng QUdpSocket để truyền tải dữ liệu nhưng do giới hạn MTU khoảng 2-5K và cần phải phân chia và tái hợp dữ liệu bản thân mình, tôi đã chuyển sang QTcpSocket.QTcpSocket không gửi dữ liệu đôi khi

Đôi khi dữ liệu được gửi đúng với QTcpSocket (đặc biệt nếu tôi ghi dữ liệu rất thường xuyên ~ 100ms một lần) nhưng đôi khi dữ liệu không được gửi. Ngay cả sau 5 giây. Và đôi khi một số khối dữ liệu được đệm trong một thời gian dài (vài giây) và sau đó được gửi cùng nhau.

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

Phía người nhận, tôi sử dụng readyRead tín hiệu để biết khi nào dữ liệu đã đến.

Làm cách nào để đảm bảo dữ liệu được gửi ngay lập tức? Có lựa chọn thay thế nào tốt hơn cho những gì tôi đang cố gắng làm không?

Chỉnh sửa :: Khi tôi viết sau khoảng thời gian dài 1 giây, tôi nhận được "QAbstractSocket::SocketTimeoutError" trên người nhận mọi người gửi sẽ gửi dữ liệu. Lỗi này không được nhận nếu người gửi ghi dữ liệu thường xuyên.
Có OKAY khi sử dụng QTcpSocket để truyền dữ liệu theo cách tôi đang làm ????

Chỉnh sửa 2: Ở phía người nhận, khi tín hiệu readyRead được phát ra, tôi lại kiểm tra while(m_socket->waitForReadyRead(500)) và tôi đã nhận được "QAbstractSocket::SocketTimeoutError" do điều này. Ngoài ra, kiểm tra này đã ngăn chặn việc phân phối các khối đơn lẻ.
Sau khi xem thêm tài liệu, có vẻ như readyRead sẽ liên tục được phát ra khi có dữ liệu mới, vì vậy không cần waitForReadyRead.
Tôi nhận được tất cả dữ liệu được gửi nhưng dữ liệu vẫn không xuất hiện ngay lập tức. Đôi khi hai phần ba được hợp nhất. Điều này có thể do sự chậm trễ về phía người nhận trong dữ liệu đọc, v.v.

+0

bạn có thể thử đặt cờ QAbstractSocket :: LowDelayOption thành setSocketOption API không? – Kunal

+0

@Kunal, tôi đã thử cả LowDelayOption & KeepAliveOption mà không thành công.Thật thú vị ngay sau khi người gửi gửi dữ liệu, người nhận sẽ hiển thị một "QAbstractSocket :: SocketTimeoutError". Điều này xảy ra khi ghi dữ liệu ở các khoảng trống trong 1 giây. –

+0

Tôi tin rằng vấn đề nằm ở phía bên nhận. Vui lòng cho chúng tôi biết cách bạn xử lý các kết nối đến. – Koying

Trả lời

2

Về phía người nhận, khi đã sẵn sàng Tín hiệu tín hiệu phát ra, tôi lại kiểm tra while(m_socket->waitForReadyRead(500)) và tôi nhận được "QAbstractSocket::SocketTimeoutError" do điều này. Ngoài ra, kiểm tra này đã ngăn chặn việc phân phối các khối đơn lẻ.

Sau khi xem thêm tài liệu, có vẻ như readyRead sẽ liên tục được phát ra khi có dữ liệu mới, vì vậy không cần waitForReadyRead. Nó đã giải quyết được vấn đề của tôi.

0

giải pháp tipical của tôi cho ứng dụng máy chủ ứng dụng khách.

về phía máy chủ:

class Server: public QTcpServer { 

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

}; 

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

trên client:

lớp Chủ đầu tư: QTcpSocket công cộng {

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

trên 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 
} 
Các vấn đề liên quan