我有一个 C++ 应用程序,使用 Boost.Asio 的 UDP 服务器从千兆本地网络设备接收高频率数据包(每秒 3500 个)。一些用户报告丢失了一些数据包。所以最后我选择同时运行 WireShark 和我的应用程序,检查 WireShark 能否接收但我的应用程序无法接收的数据包。
我发现 WireShark 并没有接收到每个数据包,似乎它会漏掉一些数据包。我的应用程序也会比 Wireshark 正确接收的数据包少一些。
我的问题:WireShark 是否可能接收到我的应用程序无法接收到的数据包?我认为也许 WireShark 对 IP 协议栈有低级别访问权限,即使这些数据包在 WireShark 中显示出来,操作系统也会将其丢弃?在 (1) 中的操作是否可能花费太长时间,以致下一个 async_receive_from
调用太晚?
我希望能得到关于此主题的意见。谢谢。
以下是我使用的代码(非常基础)。udp_server.h:
#pragma once
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <fstream>
const int MAX_BUFFER_SIZE = 65537;
using boost::asio::ip::udp;
class UDPServer
{
public:
UDPServer(boost::asio::io_service& ios, udp::endpoint endpoint)
:m_io_service(ios),
m_udp_socket(m_io_service, endpoint)
{
// Resize the buffer to max size in the component property
m_recv_buffer.resize(MAX_BUFFER_SIZE);
m_output_file.open("out.bin", std::ios::out | std::ios::binary);
StartReceive();
}
public:
void StartReceive()
{
m_udp_socket.async_receive_from(
boost::asio::buffer(m_recv_buffer), m_remote_endpoint,
boost::bind(&UDPServer::HandleReceive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
private:
void HandleReceive(const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (!error || error == boost::asio::error::message_size)
{
// Write to output -- (1)
m_output_file.sputn(&m_recv_buffer[0], bytes_transferred);
// Start to receive again
StartReceive();
}
}
boost::asio::io_service& m_io_service;
udp::socket m_udp_socket;
udp::endpoint m_remote_endpoint;
std::vector<char> m_recv_buffer;
std::filebuf m_output_file;
};
main.cpp:
include <boost/asio.hpp>
#include "udp_server.h"
const unsigned short PORT_NUMBER = 44444;
int main()
{
boost::asio::io_service ios;
boost::asio::ip::udp::endpoint endpoint(udp::endpoint(udp::v4(), PORT_NUMBER));
UDPServer server(ios, endpoint);
ios.run();
return 0;
}
std::filebuf
?它并不是用来这样使用的。只需要使用std::ofstream
(可能关闭stdio
同步)。 - edmzbind
吗?每个数据包后面都需要调用sputn
吗?在调用async_receive_from
之前需要等待sputn
返回吗?进行优化将有所帮助。但无论你做什么,有时候会丢失数据包、重复数据包或接收到乱序的数据包。如果你无法处理这些问题,就不要使用 UDP。 - David Schwartzstd::filebuf
,因为在几年前的基准测试中,它是我尝试过的最快的。我比较了文本模式和二进制模式下的std::ofstream
和std::filebuf
,而std::filebuf
明显是最快的。无论如何,在我的实际代码中,我使用另一个处理代码来执行其他操作,我不是在写入二进制文件。这只是为了调试。 - poukill