chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.88k stars 1.21k forks source link

When udp receives large packets of data, there will be a 10014 error。 #1374

Closed ml232528 closed 11 months ago

ml232528 commented 11 months ago

Send large udp packets through the system API (sendto). asio will receive an error。

boost 1.83 windwos 11 Visual Studio 2022

The code is as follows:

#pragma comment(lib,"Ws2_32.lib")
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#include <thread>

#include <boost/asio.hpp>
#include <iostream>

void SendFun();
void BoostRecv();

int main()
{  
    auto sendTh = std::make_shared<std::thread> ([]() {     
        SendFun();
        });

    auto recvTh = std::make_shared<std::thread>([]() {
        BoostRecv();
        });

    getchar();
}

void SendFun() 
{
    int iResult;
    WSADATA wsaData;
    sockaddr_in RecvAddr;
    unsigned short Port = 27015;
    char SendBuf[60000];
    int BufLen = sizeof(SendBuf);
    SOCKET SendSocket = INVALID_SOCKET;

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error: %d\n", iResult);
        return;
    }

    SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (SendSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return;
    }

    RecvAddr.sin_family = AF_INET;
    RecvAddr.sin_port = htons(Port);
    RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    while (true)
    {
        wprintf(L"Sending a datagram to the receiver...\n");
        iResult = sendto(SendSocket,
            SendBuf, BufLen, 0, (SOCKADDR*)&RecvAddr, sizeof(RecvAddr));
        if (iResult == SOCKET_ERROR) {
            wprintf(L"sendto failed with error: %d\n", WSAGetLastError());
            closesocket(SendSocket);
            return;
        }
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    iResult = closesocket(SendSocket);

    WSACleanup();

}

void ReadBuffer(std::shared_ptr<unsigned char> shBuf, int nBufLen, boost::asio::ip::udp::socket& socketudp) {

    std::shared_ptr<boost::asio::ip::udp::endpoint> remoteEndPoint = std::make_shared<boost::asio::ip::udp::endpoint>();

    socketudp.async_receive_from(boost::asio::buffer(shBuf.get(), nBufLen), *remoteEndPoint, [&shBuf,nBufLen,&socketudp](boost::system::error_code ec, std::size_t bytes_transferred) {
        if (ec) {
            std::cout << "err : " << ec.what();
        }
        else {
            std::cout << "recv : " << bytes_transferred;
        }

        ReadBuffer(shBuf, nBufLen, socketudp);
        });
}

void BoostRecv()
{
    boost::asio::io_service ioService;

    boost::asio::ip::udp::socket socketudp{ ioService, boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string("0.0.0.0"), 27015) };

    socketudp.set_option(boost::asio::socket_base::receive_buffer_size(65535));

    auto shBuf = std::shared_ptr<unsigned char>(new unsigned char[1024 * 1024], [](unsigned char* p) { delete[] p; });  

    ReadBuffer(shBuf, 1024 * 1024, socketudp);

    ioService.run();
}

Error printing as follows:

10014,系统检测到在一个调用中尝试使用指针参数时的无效指针地址。 [system:10014 at D:\浠g爜\绗笁鏂瑰伐鍏穃boost\vs2022_boost-1_83\include\boost-1_83\boost\asio\detail\win_iocp_socket_recvfrom_op.hpp:98:5 in function 'do_complete']