问题
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