Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[winsock] recvfrom()

11 réponses
Avatar
JKB
Bonjour à tous,

J'ai un petit problème avec Visual C++ (2010) et une socket.
Je viens d'écrire un bout de code qui récupère un flux UDP d'une
caméra et qui le retransmet sur plusieurs réseaux en multicast
(toujours en UDP). Ce programme fonctionne bien, à l'aide d'un
analyseur de trame, je vois passer mes paquets UDP correctement
formatés.

Je viens de m'attaquer au client. Ce client doit donc se connecter à
une socket UDP et joindre un groupe multicast. Lorsque je fais
tourner le programme compilé en debug, ça fonctionne parfaitement.
En release, la fonction recvfrom() échoue sur un timeout et je ne
comprends pas du tout ce qui se passe. La chose est compilée en 32
bits sur un Windows 7 Ultimate 64 bits avec Visual Studio 2010
professionnel.

Le port utilisé est le port UDP/34 (imposé) et ne doit pas tourner
en administrateur. 34 est inférieur à 1024, mais si c'était ça le
problème, il devrait aussi se poser en debug.

Mon code est le suivant (il figure dans une fonction privée d'une
classe) :

void xxx::initSocket()
{
char datagram[DATAGRAM_SIZE];
char flag;

int address_length;
int ios;
int timeout;

struct sockaddr_in address;
struct sockaddr_in packet_address;

struct ip_mreq mreq;

// Try to open multicast socket

if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
return;
}

// Listening from all IPv4 addresses
// TODO : port is 34 for first camera, 35 for second one... und so
// weiter !

address.sin_family = AF_INET;
address.sin_port = multicastAddress.sin_port + 0; // FIX ME !
address.sin_addr.s_addr = htonl(INADDR_ANY);

flag = -1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));

if ((bind(sock, (struct sockaddr *) &address, sizeof(address)))
!= 0)
{
close(sock);
return;
}

// Join multicast group

mreq.imr_multiaddr.s_addr = multicastAddress.sin_addr.s_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);

if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq,
sizeof(mreq)) < 0)
{
return;
}

// Wait for a packet to discover image size.

srand(time(NULL));
address_length = sizeof(packet_address);

timeout = 1000;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout,
sizeof(timeout));

while((ios = recvfrom(sock, datagram, DATAGRAM_SIZE, 0,
(struct sockaddr *) &packet_address, &address_length)) ==
SOCKET_ERROR)
{

// Ici, recvfrom() échoue sur un timeout alors que les trames
// sont bien envoyées. Le port est UDP/34 et le programme ne tourne pas
// en administrateur.

Sleep((((double) rand()) / RAND_MAX) * 1000);
}

// .....

return;
}

Je suis convaincu que mon problème n'est pas un problème de réseau.
Si c'était le cas, cela ne fonctionnerait pas en debug.
Ou il se situe entre la chaise et le clavier ou il s'agit d'un
problème microsoftien, mais il a forcément une explication
rationnelle et peut-être certains d'entre vous ont déjà observé le
même genre de dysfonctionnement.

Si quelqu'un n'avait qu'un début d'explication, je lui serai
reconnaissant de bien vouloir éclairer ma lanterne.

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr

10 réponses

1 2
Avatar
JKB
Le Thu, 3 Feb 2011 18:07:28 +0000 (UTC),
JKB écrivait :
Bonjour à tous,



Je me réponds à moi-même. Je viens de compiler le même programme
sous Linux (avec g++) et il fonctionne parfaitement (en root parce
que le port est inférieur à 1024, mais il fonctionne).

La question est donc : qu'est-ce qui change entre le release et le
debug de Visual C++ et qui ferait que ça coince.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Serge Paccalin
Le Fri, 4 Feb 2011 13:06:55 +0000 (UTC), JKB a écrit
(dans <news:, posté
dans fr.comp.lang.c++) :

La question est donc : qu'est-ce qui change entre le release et le
debug de Visual C++ et qui ferait que ça coince.



L'initialisation systématique des variables en mode debug, probablement.

--
___________
_/ _ _`_`_`_) Serge PACCALIN -- sp ad mailclub.net
_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763
Avatar
JKB
Le Sat, 5 Feb 2011 09:51:09 +0100,
Serge Paccalin écrivait :
Le Fri, 4 Feb 2011 13:06:55 +0000 (UTC), JKB a écrit
(dans <news:, posté
dans fr.comp.lang.c++) :

La question est donc : qu'est-ce qui change entre le release et le
debug de Visual C++ et qui ferait que ça coince.



L'initialisation systématique des variables en mode debug, probablement.



Oui mais non. Mauvaise piste. Il n'y a rien de non initialisé. De
plus, sous Linux avec valgrind, rien n'est renvoyé. Aucune variable
utilisée non initialisée, aucune corruption de la mémoire.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Olivier Miakinen
Bonjour,

Je viens tout juste de me rappeler un truc...

Le 03/02/2011 19:07, JKB a écrit :

[...]

Mon code est le suivant (il figure dans une fonction privée d'une
classe) :

void xxx::initSocket()
{
char datagram[DATAGRAM_SIZE];
char flag;

int address_length;
int ios;
int timeout;

struct sockaddr_in address;
struct sockaddr_in packet_address;

struct ip_mreq mreq;

// Try to open multicast socket

if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
return;
}

[...]
}



... c'est qu'avant de pouvoir utiliser les sockets sous Windows il faut
faire un appel spécifique pour les initialiser :
<http://www.cppfrance.com/codes/INITIALISER-WINSOCK_9949.aspx&gt;

Peut-être que cet appel est fait par défaut en mode debug et pas en mode
normal.
Avatar
JKB
Le Sat, 05 Feb 2011 20:24:21 +0100,
Olivier Miakinen <om+ écrivait :
Bonjour,

Je viens tout juste de me rappeler un truc...

Le 03/02/2011 19:07, JKB a écrit :

[...]

Mon code est le suivant (il figure dans une fonction privée d'une
classe) :

void xxx::initSocket()
{
char datagram[DATAGRAM_SIZE];
char flag;

int address_length;
int ios;
int timeout;

struct sockaddr_in address;
struct sockaddr_in packet_address;

struct ip_mreq mreq;

// Try to open multicast socket

if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
return;
}

[...]
}



... c'est qu'avant de pouvoir utiliser les sockets sous Windows il faut
faire un appel spécifique pour les initialiser :
<http://www.cppfrance.com/codes/INITIALISER-WINSOCK_9949.aspx&gt;

Peut-être que cet appel est fait par défaut en mode debug et pas en mode
normal.



Merci du tuyau, mais cet appel est fait dans le main (avec un 2,0
comme version). Le problème n'est donc pas là. En revanche, j'ai
oublié de préciser que le bout de code en question est lié avec Qt.
Il faudrait que je vérifie s'il n'y a pas quelque part un effet de
bord...

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Olivier Miakinen
Le 06/02/2011 10:25, JKB a écrit :

<http://www.cppfrance.com/codes/INITIALISER-WINSOCK_9949.aspx&gt;



Merci du tuyau, mais cet appel est fait dans le main



Ok.

(avec un 2,0 comme version).



Ah, la doc que j'ai trouvée était sans doute un peu vieille...

Le problème n'est donc pas là. En revanche, j'ai
oublié de préciser que le bout de code en question est lié avec Qt.
Il faudrait que je vérifie s'il n'y a pas quelque part un effet de
bord...



Si tu ne trouves pas, note quand même que ça a très peu de chances
d'être un problème de C++, et que c'est plus vraisemblablement une
question liée à l'environnement spécifique à Visual C++. Je veux dire
que tu aurais sûrement plus de réponses dans un groupe Windows que
dans ce groupe consacré au langage de programmation lui-même.

Cordialement,
--
Olivier Miakinen
Avatar
JKB
Le Mon, 07 Feb 2011 12:48:03 +0100,
Olivier Miakinen <om+ écrivait :
Le 06/02/2011 10:25, JKB a écrit :

<http://www.cppfrance.com/codes/INITIALISER-WINSOCK_9949.aspx&gt;



Merci du tuyau, mais cet appel est fait dans le main



Ok.

(avec un 2,0 comme version).



Ah, la doc que j'ai trouvée était sans doute un peu vieille...

Le problème n'est donc pas là. En revanche, j'ai
oublié de préciser que le bout de code en question est lié avec Qt.
Il faudrait que je vérifie s'il n'y a pas quelque part un effet de
bord...



Si tu ne trouves pas, note quand même que ça a très peu de chances
d'être un problème de C++, et que c'est plus vraisemblablement une
question liée à l'environnement spécifique à Visual C++. Je veux dire
que tu aurais sûrement plus de réponses dans un groupe Windows que
dans ce groupe consacré au langage de programmation lui-même.



Je suis parfaitement d'accord. J'ai d'ailleurs posé cette question
directement dans le forum dédié à Visual C++ sur l'un des sites de
Microsoft et j'attends toujours une réponse. Vu le nombre de liens
trouvés dans google concernant peu ou prou le même problème, c'est
un souci assez commun mais tout le monde propose une autre solution
et je n'ai pas encore réussi à séparer le bon grain de l'ivraie.

Entre temps, j'ai progressé. Windows 7 n'honore pas correctement
l'IGMP et transforme pour contourner le bug les trames multicast en
broadcast. Je vais déjà essayer de corriger^Wcontourner ce bug qui
AMHA est corrélé avec celui que j'observe plus loin.

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Fabien LE LEZ
On Mon, 7 Feb 2011 12:36:14 +0000 (UTC), JKB
:

J'ai d'ailleurs posé cette question
directement dans le forum dédié à Visual C++



As-tu essayé fr.comp.os.ms-windows.programmation ? (S'il existe
encore -- je n'y ai pas mis les pieds depuis des années.)
Avatar
JKB
Le Tue, 08 Feb 2011 08:04:59 +0100,
Fabien LE LEZ écrivait :
On Mon, 7 Feb 2011 12:36:14 +0000 (UTC), JKB
:

J'ai d'ailleurs posé cette question
directement dans le forum dédié à Visual C++



As-tu essayé fr.comp.os.ms-windows.programmation ? (S'il existe
encore -- je n'y ai pas mis les pieds depuis des années.)



Non, j'ai essayé le support direct de Microsoft pour l'instant,
support qui est aussi loquace qu'une carpe... Je suis en train
d'isoler les problèmes et de faire des tests avec des programmes
rudimentaires. Mon problème pue l'effet de bord entre deux
bibliothèques.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Thierry
JKB écrivait
news::

Bonjour à tous,

J'ai un petit problème avec Visual C++ (2010) et une socket.
Je viens d'écrire un bout de code qui récupère un flux UDP
d'une caméra et qui le retransmet sur plusieurs réseaux en
multicast (toujours en UDP). Ce programme fonctionne bien, à
l'aide d'un analyseur de trame, je vois passer mes paquets UDP
correctement formatés.



Les 2 (cleint et serveurà) sont linkés avec la même lib ??
De mémoire il y plusieurs lib dispo (ws32, ws32_2) qui implementent de
mêmes fonctions mais dont le comportement peut varier suivant la lib
utilisé.


--
Vainqueur du 1er WSOFRJCP
1 2