cs_billbaxter
Messages postés11Date d'inscriptionmercredi 13 juillet 2005StatutMembreDernière intervention27 juillet 2005
-
13 juil. 2005 à 23:39
cs_billbaxter
Messages postés11Date d'inscriptionmercredi 13 juillet 2005StatutMembreDernière intervention27 juillet 2005
-
16 juil. 2005 à 00:55
Bonjour,
J'ai développé une appli client-serveur avec les winsock2 en me référant aux exemples MSDN.
Ceux-ci ne présentent qu'un dialogue effectué en un seul coup sur un petit nombre d'octets (32).
J'y arrive donc sans problème, mais lorsque le send() envoie plus que la taille du buffer spécifié dans recv(), le dernier recv() reste bloqué !
Voici la boucle (simplifiée) de réception en plusieurs morceaux :
lpBufCour = lpBuf ;
bPremLu = FALSE ;
dimlus = 0 ;
for (;;)
{
// Receive data from the server socket.
if (!ReceiveInBox (ServerSock, lpBufCour, 2048, &nblus))
return FALSE ;
dimlus += nblus ;
if ((bPremLu == FALSE) && (dimlus >= OFFSET_QR_DATAS))
{ // il faut aller chercher en tête du premier sous-bloc, la dimension totale attendue
lpRhead = (struct r_inconnu *) lpBuf ;
dimbloc = lpRhead->dimbloc ;
bPremLu = TRUE ;
}
if ((DWORD)dimlus == dimbloc)
break ; // on sort de la boucle "for" <-------------- c'est le cas normal
if ((DWORD)dimlus > dimbloc)
return FALSE ;
lpBufCour += nblus ;
}
J'ai essayé en passant en mode bloquant et non bloquant, ça ne change rien.
BREF, MES DEUX QUESTIONS SONT :
1) Il semblerait que cRBufLen ait une incidence sur le fonctionnement de recv(). Quelqu'un a-t'il des infos sur une taille optimale ou maximale de ce paramètre de recv() ?
2) Comment savoir qu'il n'y a plus rien à recevoir. Faut-il attendre un recv() à 0 ou faut-il savoir (comme je l'ai fait) combien on attend d'octets, auquel cas on zappe le recv() retournant 0.
cs_aardman
Messages postés1905Date d'inscriptionmercredi 22 janvier 2003StatutMembreDernière intervention17 septembre 20123 14 juil. 2005 à 03:13
Salut,
1) Plus le buffer est gros plus tu recois d'octets d'un coup.. donc je
dirais quelques Ko. Seulement recv() n'attendra pas que ton
buffer soit plein avant de retourner, il copiera simplement les données
déja recues dans ton buffer.
2) Pour savoir combien d'octet peuvent etre lus (cad combien d'octet
seront retournés instantanément si tu appeles recv()) tu peux utiliser
ioctlsocket avec le flag FIONREAD.
Les sockets sont bloquants (par défaut), il me semble que je "gracefully close" tout comme y faut.
Le client attend donc la réponse sans connaître à priori la dimension de la réponse. Comme les sockets sont bloquants, j'attends que recv() retourne 0 pour savoir que c'est terminé.
Mon problème est que le recv() bloque indéfiniment ou presque (jusqu'à avoir WSAECONNRESET comme erreur) dès que j'ai un nombre "important" d'octets (ok avec 96, bloque avec 3229 par exemple).
Tout allait bien jusqu'alors, mais ce problème est apparu lorsque j'ai augmenté le débit entre le client et le serveur. Ca ressemble fort à un problème de synchro.
De plus ça ne le fait qu'entre deux PC particuliers !!!
Pour revenir à mon message précédent, j'ai essayé avec des dimensions variables dans recv() pour morceler différemment, et j'ai essayé en non bloquant. Même effet.
A propos des sockets non-bloquants, qui peut et doit le mettre en non-bloquant, l'émetteur, le récepteur, les deux ???
cs_billbaxter
Messages postés11Date d'inscriptionmercredi 13 juillet 2005StatutMembreDernière intervention27 juillet 2005 14 juil. 2005 à 14:44
Avant d'avoir une réponse éventuelle, je viens de trouver un truc à tester, sur www.sockets.com Apparemment, il ne faut pas faire de closesocket tant qu'on n'est pas sûr que le send a flushé tout son contenu.
Il faut que je teste (demain) :
cs_billbaxter
Messages postés11Date d'inscriptionmercredi 13 juillet 2005StatutMembreDernière intervention27 juillet 2005 16 juil. 2005 à 00:47
En fait je crois que mon code est nickel, ça marche sur des dizaines de configurations chez mes clients (poste serveur S à un endroit S et postes clients C à un endroit C) depuis des années ! Vraiment...
C'est du send receive classique, MSDN pur jus.
Ca fait une semaine que j'essaie plein de trucs (bloquant, non bloquant, shutdown, close, morcellement différent, etc...) et rien n'y fait.
Je viens de m'apercevoir que cette config qui ne marche pas est la seule qui concerne deux machines distantes dotées d'une Freebox dont l'IP fixe ne diverge que par le dernier nombre (DSLAM commun j'imagine). En effet, ces deux PC sont dans le même quartier. Adresse 78.45.72.110 pour le serveur et 78.45.72.110 pour le clients (adresses fictives évidemment)
J'en ai une troisième avec un autre fournisseur aussi dans le même quartier, et MIRACLE cette machine attaque le serveur S sans problème ! L'adresse IP est complètement différente.
En ce qui me concerne j'ai une freebox à mon domicile et j'attaque le serveur S sans problème.
Toujours plus fort, depuis le client C je peux attaquer le serveur d'un autre client situé ailleurs géographiquement.
Bref, plutôt que de mettre en doute le code, je commence donc à me demander si le pb ne vient pas d'un mauvais routage du côté de Free dans ce cas particulier, ce pb étant apparu qu'à partir de l'installation de la Freebox sur le site serveur et sur le site client. Avant, c'était moins rapide mais opérationnel !
La solution serait d'essayer un autre FAI sur le serveur, mais j'aimerais quand même comprendre.
Pour info, la partie du code qui déconne est le recv qui reste bloqué indéfiniment du coté client lorsque le serveur envoie une réponse de quelques kO (3229 octets par exemple)
cs_billbaxter
Messages postés11Date d'inscriptionmercredi 13 juillet 2005StatutMembreDernière intervention27 juillet 2005 16 juil. 2005 à 00:55
Erratum :
...
Je viens de m'apercevoir que cette config qui ne marche pas est la seule qui concerne deux machines distantes dotées d'une Freebox dont l'IP fixe ne diverge que par le dernier nombre (DSLAM commun j'imagine). En effet, ces deux PC sont dans le même quartier. Adresse 78.45.72.110 pour le serveur et 78.45.72.67 pour le clients (adresses fictives évidemment)
...
Ceci dit je crois que je vais redéposer ma question sous un autre titre car "recv() winsock2 en plusieurs morceaux", ça veut plus dire grand chose. Ca correspondait à ma première piste, abandonnée.
Je vais quand même continuer à chercher de mon côté.
A suivre...