我有一个C ++应用程序,它使用UDP服务器(使用Boost.Asio)以高频率(每秒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;
}
答案 0 :(得分:4)
这可能是WireShark获取数据包和我的应用程序 不是吗?
是。特别是,每个套接字都有自己的固定大小的传入数据缓冲区,如果内核尝试将新的传入数据包添加到该缓冲区,则缓冲区没有足够的可用空间来容纳该数据包,那么数据包不会被添加到缓冲区,因此从该套接字读取传入数据的应用程序将不会接收它。
鉴于此,WireShark的缓冲区完全有可能接受传入的数据包,但是你自己的应用程序的缓冲区却没有。
答案 1 :(得分:1)
数据包中有多少字节?你将缓冲区设为64K,大小为32K。那么3.5k * 32k
意味着112MB / s,我不认为千兆网络可以承受它。并且,您将数据包写入文件,sputn
可能阻止您接收更多数据包,因此驱动程序的缓冲区溢出,数据包被丢弃。
答案 2 :(得分:1)
总之,是的。
如果你想修复或改进这个,而不是仅仅询问它,使用多更大的套接字接收缓冲区而不是默认值,与平台允许的一样大,并确保您对该文件的写入也是缓冲的,只要您能提供足够大的缓冲区,无论您对崩溃时数据丢失的要求如何。