Comment résoudre facilement le 10040 message trop long erreur sur Wsock2
Je suis l'envoi d'une .Net application 1404 float valeurs qui constituent pour 5616 octets par l'intermédiaire d'un socket udp. Je n'ai pas d'exceptions d'envoi de cette opération.
Cependant, le programme de la réception de ces données, est une application C++, et lors de la réception d'une telle quantité de données, je reçois un 10040 message trop long erreur.
Apparemment 1480bytes est la plus longue de la taille possible pour les messages de Wsock2.
Quelle serait la méthode la plus simple, la plus propre façon de résoudre ce problème?
Merci!
EDIT: Affichage du code:
C'est mon socket J_Receive classe:
#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;
}
Et c'est comme ça que j'appelle la fonction de réception:
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);
Vous devez vous connecter pour publier un commentaire.
WSAEMSGSIZE
signifie généralement que la mémoire tampon que vous avez fourni àrecvfrom()
était plus petit que le datagramme entrant. De vérifier ou d'afficher votrerecvfrom()
code assurez-vous que vous utilisez une suffisamment grande et bien déclaré tampon. Parce que les paquets IPv4 peut (théoriquement) être jusqu'à 64 kilo-octets de taille, il est préférable de toujours utiliser un tampon de grandes.select()
: son retour n'est pas un booléen, vous devez vérifier pour les erreurs, zéro ou un nombre. Aussi, le premier argument doit pas impliquer votre descripteur de socket, c'est un nombre qui devrait être le 1er dans ce cas. Enfin, un appel à select, avec un 0 timeout signifie qu'il sera de retour immédiatement, indépendamment de savoir si il existe des données est prêt. Vous voulez probablement soitNULL
d'attendre indéfiniment, ou une valeur comme 100ms, si vous voulez regarder pour une sorte de signal de fin. En tout cas, vous avez besoin de prêter attention à laselect()
valeur de retour et de gérer tous les trois cas.select()
est destiné à bloquer sur un ou plusieurs descripteurs jusqu'à ce que l'un ou plusieurs de ceux-ci devient disponible. Quand il revient, vous à la figure de sa valeur de retour et les ensembles de descripteurs qui descripteurs ont besoin d'attention et de faire tout ce que vous devez faire. En général, vous n'en boucle sur une variable de contrôle, tels quewhile (!Done)
qui vous permet de vous éclater lors de certains de quitter la condition se produit ou si une erreur fatale apparaît. Rappelez-vous queselect()
modifie les descripteurs de jeux, donc vous devez les réinitialiser à chaque fois (ou de conserver une copie de rechange).De la lecture de la La documentation MSDN pour l'erreur
WSAEMSGSIZE
(10040):Cela signifie probablement que votre tampon de réception est trop petit, et vous avez besoin pour l'agrandir. Cela se fait avec la
socket
de la fonction et de laSO_RCVBUF
option.(const char *) &buffsize
WSAEWOULDBLOCK
, ce qui signifie que vous essayez de lire à partir d'un socket non bloquant et il n'a pas de données à lire. À propos de la taille de la mémoire tampon, après avoir défini la taille, l'utilisationgetsockopt
pour obtenir la taille réelle elle, parce que le système ne peut pas honorer votre demande.10040
vous dit d'utiliser une plus grande mémoire tampon lorsque vous appelezrecvfrom()
. Cela ne signifie PAS pour vous d'augmenter la taille de la douille interne du tampon de réception.Puisque vous savez déjà comment beaucoup de flotteurs vous vous attendez à recevoir, il suffit de déclarer un buffer assez grand pour recevoir tous, par exemple:
Winsock plus n'est certainement PAS un 1480 octets limite sur les messages.