[英]Boost async_read doesn't give me an “end of frame” flag
I'm still working on some kind of client for communication with an IP Camera. 我仍在使用某种客户端与IP摄像机进行通信。 Now I have the following issue:
现在我有以下问题:
I send a request to the camera ( a RTSP DESCRIBE
in particular ). 我向相机发送请求(特别是
RTSP DESCRIBE
)。 Now I get it's answer which looks like this: 现在我得到的答案看起来像这样:
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
This is the header of the answer, followed by a so called Session Description
which has the size shown in the field Content-Length
. 这是答案的标题,后面是所谓的
Session Description
,其大小显示在Content-Length
字段中。 Actually I don't care much for the Session Description
, I'm just interested in the Content-Base
field. 实际上,我对
Session Description
不是很在乎,我只对Content-Base
字段感兴趣。 But still, since there is some communication following on the same socket, I need to get rid of all the data. 但是,由于在同一套接字上进行了一些通信,因此我需要删除所有数据。
For receiving'm using the async_read
calls from boost::asio
. 用于使用来自
boost::asio
的async_read
调用来接收。 My code looks ( simplified ) like this: 我的代码如下所示(简化):
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));
}
This one reads at least the header ( shown above ) since its terminated by a blank line. 这个至少读取标题(如上所示),因为它以空行终止。 As usual for
async_write
it just reads some more of the data, but nevermind. 和
async_write
一样,它只读取更多数据,但是没关系。 Now to the next callback function: 现在转到下一个回调函数:
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));
}
Now this works fine as well, if I print out the number of received bytes it's always 215. 现在这也可以正常工作,如果我打印出接收到的字节数,则始终为215。
Now we go on to the critical callback: 现在我们继续进行关键回调:
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";
}
}
This part reads 220 Bytes. 此部分读取220个字节。 If I look at console Output from this call and compare it with the actualy payload of the frame ( as seen in Wireshark ) I can see that all data has been received.
如果我查看来自此调用的控制台输出并将其与帧的实际有效负载进行比较(如Wireshark中所示),我可以看到已收到所有数据。 Now I would actually assume that
async_read
would set me the eof
error. 现在我实际上假设
async_read
会给我设置eof
错误。 But instead the return code of error
is success
and so it calls async_read
again. 但是
error
的返回代码是success
,因此它再次调用async_read
。 This time there is no data to be received and it never calls the callback function ( since there will be no more incoming data ). 这次没有数据要接收,它从不调用回调函数(因为没有更多的传入数据)。
Now I actually don't know how I could determine that all data has been sent. 现在我实际上不知道如何确定所有数据都已发送。 Actually I would expect the error flag to be set.
实际上,我希望设置错误标志。
Now this is very similar to the implementation of the Boost Example for an Async HTTP client. 现在,这与Async HTTP客户端的Boost示例的实现非常相似。 Also it is done the same way in the Example Boost Async HTTP Client .
同样,在示例Boost Async HTTP Client中也以相同的方式完成。 I implemented this in another call and there it actually works.
我在另一个电话中实现了这一点,并且在这里确实有效。
Now in my opinion it should make no difference for the async_read
call wether it is HTTP or RTSP - end of frame is end of frame, if there is no more data to read. 现在在我看来,它应该对
async_read
调用没有区别,因为它是HTTP或RTSP - 如果没有更多数据要读取,则帧结束是帧结束。
I'm also aware that according to the boost documentation I am using 我也知道根据我使用的boost文档
void async_read(
AsyncReadStream & s,
basic_streambuf< Allocator > & b,
CompletionCondition completion_condition,
ReadHandler handler);
which means the function will continue until 这意味着该功能将持续到
The supplied buffer is full (that is, it has reached maximum size). The completion_condition function object returns 0.
So if there is no more data to read, it just continues. 因此,如果没有更多数据要读取,它将继续。 But I also tried the overloaded function without the
CompletionCondition
parameter, which should return when an error occurs ( EOF
!!! ) - But this just won't callback either... 但我也尝试了没有
CompletionCondition
参数的重载函数,它应该在发生错误时返回( EOF
!!!) - 但这只是不会回调...
Any suggestions? 有什么建议么? I just don't get what I'm doing wrong...
我只是不明白我在做什么错...
I have written an RTSP client and server library using boost asio and can offer the following advice: The RTSP message syntax is generic: there is no need for different DESCRIBE and SETUP handlers. 我已经使用boost asio编写了RTSP客户端和服务器库,并可以提供以下建议:RTSP消息语法是通用的:不需要其他DESCRIBE和SETUP处理程序。 In general
一般来说
boost::asio::async_read_until("\\r\\n\\r\\n")
boost::asio::async_read_until("\\r\\n\\r\\n")
Content-Length
header Content-Length
标头 boost::asio::transfer_at_least(content_length)
boost::asio::transfer_at_least(content_length)
Further, why are you expecting an EOF? 此外,您为什么要期待EOF? The connection is still open: the server is waiting for either another SETUP or a PLAY request and typically won't close the connection until the RTSP TCP connection has been timed out, which has a default value of 60 seconds according to RFC2326 .
连接仍处于打开状态:服务器正在等待另一个SETUP或PLAY请求,并且通常直到RTSP TCP连接超时(根据RFC2326的默认值为60秒)后,才会关闭连接。
If in your application, you have completed interaction with the RTSP server, close the connection after you have read the response. 如果您已在应用程序中完成与RTSP服务器的交互,请在阅读响应后关闭连接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.