Receiving UDP packets at high frequency : packet loss?

Viewed 2390

I have a C++ application which uses a UDP Server (using Boost.Asio) that receives packets from a gigabit local network device at a high frequency (3500 packets per second). Some users report a few packet losses. So in the end I chose to run in parallel WireShark and my application to check if there are any packets that WireShark is able to receive but not my application.

What I found is that WireShark does not receive every packet, it seems that it misses some. My application misses also a few more frames that Wireshark received correctly.

My questions : Is it possible WireShark gets packets that my application does not ? I thought maybe WireShark has low-level access to the IP stack and packets are discarded by the OS even if they are shown in WireShark ? Is it possible that the operation in (1) takes too much time such that the next async_receive_from is called too late? I would like to have opinions on this subject. Thanks.

Here is the code I use (quite basic). 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;
}
3 Answers
Related