我还在使用某种客户端与IP摄像头进行通信。现在我有以下问题:
我向相机发送请求(特别是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
字段感兴趣。但是,由于在同一个套接字上有一些通信,我需要删除所有数据。
使用来自async_read
的{{1}}来电接收。
我的代码看起来(简化)像这样:
boost::asio
这个至少读取标题(如上所示),因为它以空行终止。像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
现在这也可以正常工作,如果我打印出接收的字节数,它总是215。
现在我们继续进行关键回调:
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));
}
这部分读取220字节。如果我查看来自此调用的控制台输出并将其与帧的实际有效负载进行比较(如Wireshark中所示),我可以看到已收到所有数据。现在我实际上假设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";
}
}
会给我async_read
错误。但相反,eof
的返回代码为error
,因此它再次调用success
。这次没有数据要接收,它从不调用回调函数(因为没有更多的传入数据)。
现在我实际上不知道如何确定所有数据都已发送。实际上我希望设置错误标志。
现在,这与Async HTTP客户端的Boost示例的实现非常相似。它也在Example Boost Async HTTP Client中以相同的方式完成。我在另一个电话中实现了这个,它确实有效。
现在在我看来,对于async_read
调用它应该没有区别,因为它是HTTP或RTSP - 如果没有更多数据需要读取,则帧结束是帧结束。
我也知道根据我使用的提升文档
async_read
表示该功能将持续到
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
!!!) - 但这不会回调...
有什么建议吗?我只是不知道我做错了什么......
答案 0 :(得分:3)
我使用boost asio编写了一个RTSP客户端和服务器库,可以提供以下建议: RTSP消息语法是通用的:不需要不同的DESCRIBE和SETUP处理程序。一般来说
boost::asio::async_read_until("\r\n\r\n")
Content-Length
标题boost::asio::transfer_at_least(content_length)
此外,您为什么期待EOF?连接仍处于打开状态:服务器正在等待另一个SETUP或PLAY请求,并且通常不会关闭连接,直到RTSP TCP连接超时,根据{{3},默认值为60秒}。
如果您的应用程序中已完成与RTSP服务器的交互,请在阅读响应后关闭连接。