2017-06-21 152 views
0

我需要實現以300 Hz(每秒300個採樣)讀取數據的客戶端。當使用C套接字時,一切都可以接受,因爲我需要運行一個連續的while循環來從服務器獲取數據(阻止客戶端處理其他任何事情)。 所以,我決定嘗試移動到QTcpsocket,以處理來自其他對象到客戶端對象的信號。但是,當我連接與QTcpSocket,並連接信號讀取使用QTcpSocket持續快速使用

connect(socket,&QTcpSocket::readyRead, this, &client::handleReadyRead, Qt::ConnectionType::QueuedConnection); 

這是我的處理程序 -

QByteArray b = socket->read(12); 
int packetLength = (unsigned char)b[6] << CHAR_BIT; 
packetLength |= (unsigned char)b[7]; 
b = socket->read(packetLength); 

(我得到每包12字節長頭) 現在我得到一個非常慢速客戶端 - 它每秒處理大概3個樣本......我檢查了看有多少bytesavailable()返回,並且它看起來像數據堆積在套接字緩衝區中。 我在做什麼錯?我必須得到一個非常快速的客戶,但我不確定我閱讀的方式是最佳的。 有沒有更有效的方法來做到這一點?

謝謝

+2

配置您的應用程序,看看瓶頸在哪裏。 –

+0

我實際上使用一個小型項目來測試它,所以它幾乎只是客戶端運行。分析表明,事件循環需要很長時間,但可以避免嗎? – JLev

+0

您正在調用'socket-> read(packetLength)'而不知道'packetLength'字節是否可用。如果它們不是,則下一次讀取將與數據流不同步。 –

回答

1

您當前handleReadyRead假設一個完整的數據包可用於讀取和數據包邊界已被保留。 TCP不能這樣工作 - 它只是一個字節流。

更好的方法可能是將數據累加到QByteArray中,並在數據包可用時從該QByteArray中讀取數據包。

因此,假設您的client類有一個數據成員...

QByteArray m_data; 

我期望的邏輯是這樣的......

void handleReadyRead() 
{ 

    /* 
    * Append all available data to m_data. 
    */ 
    m_data.append(socket->readAll()); 

    /* 
    * Now work our way through m_data processing complete 
    * packets as we find them. At any given point offset 
    * is the total size of all complete packets (including 
    * headers) processed thus far. 
    */ 
    int offset = 0; 
    while (m_data.length() >= offset + 12) { 

    /* 
    * We have enough data for a header so read the packet length. 
    */ 
    int packetLength = (unsigned char)m_data[offset + 6] << CHAR_BIT; 
    packetLength  |= (unsigned char)m_data[offset + 7]; 

    /* 
    * Check to see if we have sufficient data for the packet 
    * body. If not then we're done for the time being. 
    */ 
    if (m_data.length() < offset + 12 + packetLength) 
     break; 

    /* 
    * There is enough data for the complete packet so read it. 
    * Note that the following will include the header data in the 
    * packet variable. If that's not desired then change it to... 
    * 
    * auto packet = m_data.mid(offset + 12, packetLength); 
    */ 
    auto packet = m_data.mid(offset, 12 + packetLength); 

    /* 
    * Do whatever you want with the packet. 
    */ 
    do_something_with_the_packet(packet); 

    /* 
    * Update the offset according to the amount of data read. 
    */ 
    offset += 12 + packetLength; 
    } 

    /* 
    * Finally, remove the data processed from the beginning of 
    * the QByteArray. 
    */ 
    if (offset) 
    m_data = m_data.right(data.size() - offset); 
} 

以上是未經檢驗的,但肯定是沿着我過去使用的代碼行。

+0

這真的很有用,謝謝。現在我只是想知道爲什麼我要以錯誤的順序獲取數據包.... – JLev