我仍然在與IP攝像機通信的某種客戶端上工作。現在我有以下問題:Boost async_read不給我一個「幀結束」標誌
我向相機發送請求(特別是RTSP DESCRIBE
)。現在,我得到它的答案,看起來像這樣:
RTSP/1.0 200 OK
CSeq: 2
Date: Thu, Jan 01 1970 00:31:41 GMT
Content-Base: rtsp://192.168.0.42/mpeg4?mode=Live&stream=-1&buffer=0&seek=0&fps=100& metainfo=/
Content-Type: application/sdp
Content-Length: 517
這是答案的頭部,接着是所謂Session Description
其在該領域Content-Length
顯示的大小。實際上我並不在乎Session Description
,我只是對Content-Base
領域感興趣。但是,由於在同一個套接字上有一些通信,所以我需要刪除所有的數據。
用於接收來自boost::asio
的async_read
來電。 我的代碼如下(簡化的)是這樣的:由於通過一個空行其終止
CommandReadBuffer::CallbackFromAsyncWrite()
{
boost::asio::async_read_until(*m_Socket, m_ReceiveBuffer,"\r\n\r\n",
boost::bind(&CommandReadBuffer::handle_rtsp_describe, this->shared_from_this(),
boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
}
這一個至少讀取頭(如上所示)。像往常一樣async_write
它只是讀取更多的數據,但從來沒有想過。現在,下一個回調函數:
void CommandReadBuffer::handle_rtsp_describe(const boost::system::error_code& err,size_t bytesTransferred)
{
std::istream response_stream(&m_ReceiveBuffer);
std::string header;
// Just dump the data on the console
while (std::getline(response_stream, header))
{
// Normally I would search here for the desired content-base field
std::cout << header << "\n";
}
boost::asio::async_read(*m_Socket, m_ReceiveBuffer, boost::asio::transfer_at_least(1),
boost::bind(&CommandReadBuffer::handle_rtsp_setup, this->shared_from_this(),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
現在能正常工作,以及,如果我打印出接收的字節數,它總是215
現在,我們去到關鍵的回調:
void CommandReadBuffer::handle_rtsp_setup(const boost::system::error_code& err, size_t bytesTransferred)
{
std::cout << "Error: " << err.message() << "\n";
if (!err)
{
// Write all of the data that has been read so far.
std::cout << &m_ReceiveBuffer;
// Continue reading remaining data until EOF.
m_DeadlineTimer->async_wait(boost::bind(&CommandReadBuffer::handleTimeout, this->shared_from_this(),boost::asio::placeholders::error));
boost::asio::async_read(*m_Socket, m_ReceiveBuffer, boost::asio::transfer_at_least(1),
boost::bind(&CommandReadBuffer::handle_rtsp_setup, this->shared_from_this(),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
else if (err != boost::asio::error::eof)
{
std::cout << "Error: " << err.message() << "\n";
}
else
{
std::cout << "End of Frame " << err.message() << "\n";
}
}
該部分讀取220個字節。如果我查看這個調用的console輸出,並將其與幀的實際有效負載進行比較(如Wireshark所示),我可以看到所有數據都已收到。現在我實際上會假設async_read
會將我設爲eof
錯誤。但是,error
的返回碼是success
,因此它再次調用async_read
。這次沒有要接收的數據,也不會調用回調函數(因爲不會有更多的傳入數據)。
現在我實際上不知道如何才能確定所有數據都已發送。其實我會期待錯誤標誌被設置。
現在,這與異步HTTP客戶端的Boost示例的實現非常相似。在Example Boost Async HTTP Client中也是這樣做的。我在另一個調用中實現了這一點,並且它實際上工作。
現在我認爲它應該是沒有區別的async_read
呼叫它是HTTP或RTSP - 幀的結尾是幀的結尾,如果沒有更多的數據要讀取。
我也知道,根據Boost文檔我使用
void async_read(
AsyncReadStream & s,
basic_streambuf<Allocator> & b,
CompletionCondition completion_condition,
ReadHandler handler);
這意味着該功能將一直持續到
The supplied buffer is full (that is, it has reached maximum size). The completion_condition function object returns 0.
所以,如果沒有更多的數據閱讀,它只是繼續。 但我也試過重載函數沒有CompletionCondition
參數,當錯誤發生時應該返回(EOF
!) - 但是,這只是不會回調要麼...
有什麼建議?我只是不明白我在做什麼錯...
與EOF的好處...我可能在我的腦海裏有什麼錯誤!那麼我確實向你告訴我的方向走了。但在這一點上有一個問題:當我收到對SETUP或PLAY請求的回覆時,我永遠不會在頭文件中獲得「content-length」字段......它從來沒有或只是在這種特殊情況下? – Toby 2012-02-21 08:48:39
SETUP和PLAY請求沒有消息正文。根據RFC2326,只是在響應中返回消息體的DESCRIBE和GET_PARAMETER請求:「...返回消息體的所有方法。在此規範中,DESCRIBE和GET_PARAMETER屬於此類。」 – Ralf 2012-02-21 08:57:42
好吧好吧,我想我現在就明白了!感謝您的幫助!! – Toby 2012-02-21 12:29:31