高频接收UDP数据包:丢包?
Receiving UDP packets at high frequency : packet loss?
我有一个 C++ 应用程序,它使用 UDP 服务器(使用 Boost.Asio),以高频率(每秒 3500 个数据包)从千兆位本地网络设备接收数据包。一些用户报告了一些数据包丢失。所以最后我选择 运行 并行 WireShark 和我的应用程序来检查是否有 WireShark 能够接收但我的应用程序不能接收的数据包。
我发现WireShark并没有收到每个数据包,似乎漏掉了一些。我的应用程序还错过了 Wireshark 正确接收的更多帧。
我的问题:WireShark 是否可能获取我的应用程序未获取的数据包?我想也许 WireShark 对 IP 堆栈具有低级访问权限,并且数据包被 OS 丢弃,即使它们显示在 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;
}
一个数据包有多少字节?您将缓冲区设置为 64K,让大小为 32K。然后 3.5k * 32k
表示 112MB/s,我认为千兆网络负担不起。并且,你将数据包写入文件,sputn
可能会阻止你接收更多的数据包,因此驱动程序的缓冲区溢出,数据包被丢弃。
Is this possible that WireShark get a packet and that my application
does not ?
是的。特别是,每个套接字都有自己的固定大小的传入数据缓冲区,如果此时内核试图将新的传入数据包添加到该缓冲区,则缓冲区没有足够的可用 space 来容纳该数据包,则该数据包将不会添加到缓冲区,因此从该套接字读取传入数据的应用程序将不会收到它。
鉴于此,WireShark 的缓冲区完全有可能有空间来接受传入的数据包,但您自己的应用程序的缓冲区却没有。
一句话,是的
如果你想修复或改进这个问题,与其只是询问,不如使用much 比默认设置更大的套接字接收缓冲区,与平台允许的一样大,并确保您对文件的写入也被缓冲,无论您对数据丢失的要求如何,都可以提供尽可能大的缓冲区崩溃。
我有一个 C++ 应用程序,它使用 UDP 服务器(使用 Boost.Asio),以高频率(每秒 3500 个数据包)从千兆位本地网络设备接收数据包。一些用户报告了一些数据包丢失。所以最后我选择 运行 并行 WireShark 和我的应用程序来检查是否有 WireShark 能够接收但我的应用程序不能接收的数据包。
我发现WireShark并没有收到每个数据包,似乎漏掉了一些。我的应用程序还错过了 Wireshark 正确接收的更多帧。
我的问题:WireShark 是否可能获取我的应用程序未获取的数据包?我想也许 WireShark 对 IP 堆栈具有低级访问权限,并且数据包被 OS 丢弃,即使它们显示在 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;
}
一个数据包有多少字节?您将缓冲区设置为 64K,让大小为 32K。然后 3.5k * 32k
表示 112MB/s,我认为千兆网络负担不起。并且,你将数据包写入文件,sputn
可能会阻止你接收更多的数据包,因此驱动程序的缓冲区溢出,数据包被丢弃。
Is this possible that WireShark get a packet and that my application does not ?
是的。特别是,每个套接字都有自己的固定大小的传入数据缓冲区,如果此时内核试图将新的传入数据包添加到该缓冲区,则缓冲区没有足够的可用 space 来容纳该数据包,则该数据包将不会添加到缓冲区,因此从该套接字读取传入数据的应用程序将不会收到它。
鉴于此,WireShark 的缓冲区完全有可能有空间来接受传入的数据包,但您自己的应用程序的缓冲区却没有。
一句话,是的
如果你想修复或改进这个问题,与其只是询问,不如使用much 比默认设置更大的套接字接收缓冲区,与平台允许的一样大,并确保您对文件的写入也被缓冲,无论您对数据丢失的要求如何,都可以提供尽可能大的缓冲区崩溃。