How to easily solve the 10040 message too long error on Wsock2

放肆的年华 提交于 2021-01-27 21:36:32

问题


I'm sending from a .Net application 1404 float values which make up for 5616 bytes through an udp socket. I get no exceptions off this operation.

However, the program receiving those data, is a C++ application, and when receiving such amount of data I get a 10040 message too long error.

Apparently 1480bytes is the longest size possible for messages in Wsock2.

What would be the easiest, cleanest way to fix this?

Thanks!

EDIT: Posting some code:

This is my socket J_Receive class:

#include "J_Receive.h"


#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#if defined (WIN32) && !defined(__CYGWIN__)
#include <winsock.h>
#else
#include <unistd.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/time.h>
#endif
#include <string.h>

#include <iostream>

using namespace sockets;

J_Recibir::J_Recibir( void )
{
    _port = 0;
    _initialized = false;
    _buffer = 0L;
}

J_Recibir::~J_Recibir( void )
{
#if defined (WIN32) && !defined(__CYGWIN__)
    closesocket( _so);
#else
    close( _so );
#endif
}

bool J_Recibir::init( void )
{
#if defined(WIN32) && !defined(__CYGWIN__)
    WORD version = MAKEWORD(1,1);
    WSADATA wsaData;
    // First, we start up Winsock
    WSAStartup(version, &wsaData);
#endif

    if( _port == 0 )
    {
    fprintf( stderr, "Receiver::init() - port not defined\n" );
    return false;
    }

    if( (_so = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
    {
        perror( "Socket" );
    return false;
    }



    /*int buffsize  = 50000;
    setsockopt( _so, SOL_SOCKET, SO_RCVBUF, (const char*)&buffsize, sizeof(buffsize));*/

#if defined (WIN32) && !defined(__CYGWIN__)
//    const BOOL on = TRUE;
//    setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(int));
#else
    int on = 1;
    setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
#endif




//    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port   = htons( _port );
#if defined (WIN32) && !defined(__CYGWIN__)
    saddr.sin_addr.s_addr =  htonl(INADDR_ANY);
#else
    saddr.sin_addr.s_addr =  0;
#endif

    if( bind( _so, (struct sockaddr *)&saddr, sizeof( saddr )) < 0 )
    {
        perror( "bind" );
        return false;
    }

    u_long iMode = 1;       // 1 para No bloqueante, 0 para bloqueante
    ioctlsocket(_so, FIONBIO, &iMode);

    _initialized = true;
    return _initialized;
}


void J_Recibir::setPort( const short port )
{
    _port = port;
}

void J_Recibir::setBuffer( void *buffer, const unsigned int size )
{
    _buffer = buffer;
    _buffer_size = size;
}

int J_Recibir::sync( void )
{
    if(!_initialized) init();

    if( _buffer == 0L )
    {
        fprintf( stderr, "Receiver::sync() - No buffer\n" );
        return -1;
    }

#if defined(__linux) || defined(__FreeBSD__) || defined( __APPLE__ )
    socklen_t 
#else
    int
#endif
        size = sizeof( struct sockaddr_in );

    fd_set fdset;
    FD_ZERO( &fdset );
    FD_SET( _so, &fdset );

    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 0;

#if defined (WIN32) && !defined(__CYGWIN__)
//    saddr.sin_port   = htons( _port );
    recvfrom( _so, (char *)_buffer, _buffer_size, 0, (sockaddr*)&saddr, &size );


//    recvfrom(sock_Receive, szMessage, 256, 0, (sockaddr*)&addr_Cli, &clilen)
    int err = WSAGetLastError ();
    if (err!=0){
        fprintf( stderr, "Receiver::sync() - error %d\n",err );
        perror("Error: ");
    }

    while( select( _so+1, &fdset, 0L, 0L, &tv ) )
    {
        if( FD_ISSET( _so, &fdset ) )
        {
            recvfrom( _so, (char *)_buffer, _buffer_size, 0, (sockaddr*)&saddr, &size );
        }
    }
#else
    recvfrom( _so, (caddr_t)_buffer, _buffer_size, 0, 0, &size );
    while( select( _so+1, &fdset, 0L, 0L, &tv ) )
    {
        if( FD_ISSET( _so, &fdset ) )
        {
            recvfrom( _so, (caddr_t)_buffer, _buffer_size, 0, 0, &size );
        }
    }
#endif

    if (err!=0) return -1;
    else        return 0;
}

And this is how I call the receive function:

     sockets::J_Receiver receiverGUI = new sockets::J_Recibir();
     receiverGUI->setPort(4020);
     nDatosGUI = 1404;
     float* datosGUI = new datosGUI[nDatosGUI ];
     receiverGUI->setBuffer((void *)datosGUI, sizeof(float)*nDatosGUI);

回答1:


WSAEMSGSIZE usually means that the buffer you provided to recvfrom() was smaller than the incoming datagram. Check or post your recvfrom() code to make sure you are using a sufficiently large and correctly declared buffer. Because IPv4 packets can (theoretically) be up to 64 kilobytes in size, it is safest to always use a buffer that large.




回答2:


Reading from the MSDN documentation for error WSAEMSGSIZE (10040):

Message too long.

A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram was smaller than the datagram itself.

This probably means that your receive buffer is too small, and you need to enlarge it. This is done with the setsockopt function and the SO_RCVBUF option.




回答3:


10040 is telling you to use a larger buffer when you call recvfrom(). It does NOT mean for you to increase the size of the socket's internal receive buffer.

Since you already know how many floats you are expecting to receive, simply declare a buffer large enough to receive them all, eg:

float buffer[1404];
int ret = recvfrom(..., (char*)&buffer[0], sizeof(buffer), ...);

Winsock most certainly does NOT have a 1480 byte limit on messages.



来源:https://stackoverflow.com/questions/9378146/how-to-easily-solve-the-10040-message-too-long-error-on-wsock2

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!