gpt4 book ai didi

c++ - Boost async_read 没有给我一个 "end of frame"标志

转载 作者:行者123 更新时间:2023-11-30 03:03:31 24 4
gpt4 key购买 nike

我仍在开发某种与 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 描述,其大小显示在Content-Length 字段中。其实我不太关心 Session Description ,我只对 Content-Base 字段感兴趣。但是,由于在同一个套接字上有一些通信,我需要删除所有数据。

用于接收来自 boost::asioasync_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 字节。如果我查看此调用的控制台输出并将其与帧的实际有效负载进行比较(如 Wireshark 中所示),我可以看到所有数据都已收到。现在我实际上假设 async_read 会给我设置 eof 错误。但 error 的返回码是 success ,因此它再次调用 async_read 。这次没有要接收的数据,它也不会调用回调函数(因为不会再有传入数据)。

现在我真的不知道如何确定所有数据都已发送。实际上我希望设置错误标志。

现在这与异步 HTTP 客户端的 Boost 示例的实现非常相似。在 Example Boost Async HTTP Client 中也是以同样的方式完成的。 .我在另一个电话中实现了这个,它确实有效。

现在在我看来,无论是 HTTP 还是 RTSP,对于 async_read 调用应该没有区别 - 如果没有更多数据要读取,帧结束就是帧结束。

我也知道根据我正在使用的 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 !!!) - 但这也不会回调.. .

有什么建议吗?我只是不明白我做错了什么......

最佳答案

我已经使用 boost asio 编写了一个 RTSP 客户端和服务器库,可以提供以下建议:RTSP 消息语法是通用的:不需要不同的 DESCRIBE 和 SETUP 处理程序。一般

  • 写一个 RTSP 请求
  • 读取响应执行 boost::asio::async_read_until("\r\n\r\n")
  • 然后检查 Content-Length header
  • 如果 content_length > 0 执行 boost::asio::transfer_at_least(content_length)

此外,您为什么期待 EOF?连接仍然打开:服务器正在等待另一个 SETUP 或 PLAY 请求,并且通常不会关闭连接,直到 RTSP TCP 连接超时,根据 RFC2326 的默认值为 60 秒| .

如果在您的应用程序中,您已完成与 RTSP 服务器的交互,请在阅读响应后关闭连接。

关于c++ - Boost async_read 没有给我一个 "end of frame"标志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9314443/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com