2017-06-21 3 views
0

300Hz(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

あなたは 'packetLength'バイトが利用可能かどうかを知らずに' socket-> read(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

関連する問題