Perte de paquets sous TCP

Le
Jean-Christophe
Avec un soft maison qui utilise winsock2, je teste une com en TCP
entre deux PC sous XP, et en local via Ethernet ca marche a 100 %.
Par contre via Internet entre deux PC (distants de 500 km)
il y a des pertes de quelques %.
Ca reste faible et j'ai une couche soft qui s'occuppe des time-out
et des retry, donc l'ensemble fonctionne comme il faut.
Mais je ne comprends pas la raison pour laquelle des paquets
envoyes n'arrivent pas a destination: est-ce qu'en mode
TCP le transport ne garantit pas la livraison des paquets ?
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
GuiGui
Le #19849981
Jean-Christophe a écrit :
Avec un soft maison qui utilise winsock2, je teste une com en TCP
entre deux PC sous XP, et en local via Ethernet ca marche a 100 %.
Par contre via Internet entre deux PC (distants de 500 km)
il y a des pertes de quelques %.
Ca reste faible et j'ai une couche soft qui s'occuppe des time-out
et des retry, donc l'ensemble fonctionne comme il faut.
Mais je ne comprends pas la raison pour laquelle des paquets
envoyes n'arrivent pas a destination: est-ce qu'en mode
TCP le transport ne garantit pas la livraison des paquets ?



Je ne comprend pas à quel niveau tu te situe avec ton soft. Tu ouvres un
socket tcp en te basant sur des appels système ou tu refais le TCP en
utilisant la couche IP ? Parce que je ne vois pas de raisons de perdre
des paquets en TCP.
Le Forgeron
Le #19850361
Le 29/07/2009 19:56, GuiGui nous fit lire :
Jean-Christophe a écrit :
Avec un soft maison qui utilise winsock2, je teste une com en TCP
entre deux PC sous XP, et en local via Ethernet ca marche a 100 %.
Par contre via Internet entre deux PC (distants de 500 km)
il y a des pertes de quelques %.
Ca reste faible et j'ai une couche soft qui s'occuppe des time-out
et des retry, donc l'ensemble fonctionne comme il faut.
Mais je ne comprends pas la raison pour laquelle des paquets
envoyes n'arrivent pas a destination: est-ce qu'en mode
TCP le transport ne garantit pas la livraison des paquets ?



Je ne comprend pas à quel niveau tu te situe avec ton soft. Tu ouvres un
socket tcp en te basant sur des appels système ou tu refais le TCP en
utilisant la couche IP ? Parce que je ne vois pas de raisons de perdre
des paquets en TCP.



Pareil.

Surtout qu'au niveau TCP, c'est un double flux d'octets, pas des paquets, qui est géré.
Maintenant, réimplémenter des time-out & retry au dessus de TCP me parait bizarre.
"A la place" au lieu de "au dessus" ?

Ou alors c'est pas du TCP ? Ou bien le soft réfait TCP lui-même, et donc fait des paquets IP ?

TCP, c'est du transport, de bout en bout: C'est les extrémités qui vérifient et
s'organisent si il y a des pertes. Les intermédiaires n'en ont rien à cirer que la
communication soit TCP ou autres (sauf les NAT/firewall...) et ne voient que des paquets
IP, potentiellement dans le désordre, et pas forcément tous ceux de la connexion.

Et puis 500 km, c'est à vol d'oiseau... si ça se trouve, les paquets vont se balader en
norvège, passe par Dallas puis reviennent par Bordeaux (surtout si les FAI sont différents).
Yannick Palanque
Le #19850471
Le Wed, 29 Jul 2009 21:15:50 +0200,
Le Forgeron
si ça se trouve, les paquets vont se balader en
norvège, passe par Dallas puis reviennent par Bordeaux
(surtout si les FAI sont différents).


^^^^^^^

Si tout ces paquets circulent au seint du même F.A.I., j'ose espérer
qu'ils ne vont pas emprunter ces chemins pour une distance de 500
km. ;-)

--
Yannick Palanque
Jean-Christophe
Le #19850801
On Jul 29, 6:56 pm, GuiGui
Tu ouvres un socket tcp en te basant sur des appels système



Oui. J'utilise les fonctions standard :

socket();
bind();
listen();
accept();
recv();
send();
closesocket();

ou tu refais le TCP en utilisant la couche IP ?



Non.

Parce que je ne vois pas de raisons de perdre des paquets en TCP.



Moi non plus.
Tout marche sans aucun probleme a 100 % en local sous Ethernet
(un LAN avec juste un routeur entre les deux machines)
les donnees envoyees sont toujours recues, et dans les deux sens,
alors pour moi ca valide le code de mon programme de com.

Par Internet ca fonctionne, mais il arrive, bien que ce
soit rare donc pas genant en pratique, que quelquefois des
donnees envoyees par send() ne soient pas recues (par recv)
Et c'est lorsque j'ai constate cela que j'ai implemente un handshake
avec timeout et renvoi des donnees en cas de non-reception d'un ACK.
Mais je ne m'y attendais pas du tout : j'ai toujours lu partout
que la couche TCP garantit que les donnees soient delivrees.
Des idees ?
Jean-Christophe
Le #19850861
On Jul 29, 8:15 pm, Le Forgeron
Surtout qu'au niveau TCP, c'est un double flux d'octets, pas des paquets, qui est géré.



Oui, desole, je n'interviens pas du tout au niveau des paquets,
je voulais dire : "donnees". Mais ces donnees
sont bien encapsulees dans les paquets, non ?

Maintenant, réimplémenter des time-out & retry au dessus de TCP me pa rait bizarre.



A moi aussi.

"A la place" au lieu de "au dessus" ?



Au dessus.

Ou alors c'est pas du TCP ?



Si, si.

Ou bien le soft réfait TCP lui-même, et donc fait des paquets IP ?



Non je ne refais pas le TCP, j'ouvre un socket via
winsock puis appelle les fonctions standard de la DLL.

TCP, c'est du transport, de bout en bout: C'est les extrémités qui v érifient et
s'organisent si il y a des pertes. Les intermédiaires n'en ont rien à cirer que la
communication soit TCP ou autres (sauf les NAT/firewall...) et ne voient que des paquets
IP, potentiellement dans le désordre, et pas forcément tous ceux de l a connexion.




Justement je ne comprends pas que des donnees
envoyees sous TCP ne soient pas recues a l'autre bout.
D'autant plus que ca marche nickel en local, 0 % de pertes.

Et puis 500 km, c'est à vol d'oiseau... si ça se trouve, les paquets vont se balader en
norvège, passe par Dallas puis reviennent par Bordeaux (surtout si les FAI sont différents).



C'est exact.
Le Forgeron
Le #19851601
Le 29/07/2009 22:52, Jean-Christophe nous fit lire :
On Jul 29, 6:56 pm, GuiGui



socket(), avec AF_INET (ou PF_INET), SOCK_STREAM et probablement 0 en protocol, c'est bien
ça ?

Parce que je ne vois pas de raisons de perdre des paquets en TCP.



Moi non plus.
Tout marche sans aucun probleme a 100 % en local sous Ethernet
(un LAN avec juste un routeur entre les deux machines)
les donnees envoyees sont toujours recues, et dans les deux sens,
alors pour moi ca valide le code de mon programme de com.

Par Internet ca fonctionne, mais il arrive, bien que ce
soit rare donc pas genant en pratique, que quelquefois des
donnees envoyees par send() ne soient pas recues (par recv)



Attention, il n'y a pas forcément un recv par send avec TCP.
Sur un lan, il est possible que les temps de réponses et propagations fassent que chaque
bloc survive à la traversé.
Au travers d'un réseau plus complexe, on peut avoir des comportements différents:
aggrégation de données retransmises, fermeture de fenêtres...
J'espère que tes données/messages sont correctement délimités dans le flux d'octets que tu
émets et reçoit.

Un truc quand même: la séquence "socket-bind-listen-accept" et "close" (d'ailleurs,
pourquoi closesocket ? normalement c'est close()... particularité windows que je ne
connais pas ?) n'a bien lieu qu'une seule fois, dans toute la vie de l'application,
n'est-ce pas ?
on n'est pas dans le cas d'un client qui ouvre une connexion pour chaque "message" a
traité, si ?

Et c'est lorsque j'ai constate cela que j'ai implemente un handshake
avec timeout et renvoi des donnees en cas de non-reception d'un ACK.



Et là, j'ai l'impression qu'au lieu d'attendre normalement la retransmission, ton appli
s'impatiente et court-circuite la marche normale (et c'est pas son boulot, c'est celui du
transport, en l'occurence TCP; Si tu as des besoins de réactivité, TCP n'est pas le bon
transport).
Et je m'interroge, comment l'autre coté gère la réception en double des messages ?

Bref, peux-tu détailler comment tu renvoies les données ?

Mais je ne m'y attendais pas du tout : j'ai toujours lu partout
que la couche TCP garantit que les donnees soient delivrees.
Des idees ?



Juste une angoisse: pour chaque "échange", ton architecture ouvre une nouvelle connexion.

Ou bien... tu ne regardes pas le retour de send().
Il renvoie le nombre d'octets envoyés.
Sur un Lan, il épuise difficilement la fenêtre de transmission, donc quand tu demandes à
envoyer 2000 octets, il réussit.
Au travers d'Internet... la fenêtre est beaucoup plus occupée (à cause du temps de
traversée), il peut donc n'en envoyer que 1700 (par exemple)... d'où des "paquets" qui te
manque à l'arrivée. En fait, ils ne sont jamais partis, et c'est ta faute.
send() t'a répondu 1700... c'était à toi de revenir plus tard pour les 300 restants.

Je m'étonne d'ailleurs que tu n'ai pas de select() dans tes fonctions. (ne serait-ce que
pour savoir quand il redevient possible d'écrire dans la socket, dont le buffer n'est
JAMAIS infini).
GuiGui
Le #19852851
Le Forgeron a écrit :
Le 29/07/2009 22:52, Jean-Christophe nous fit lire :
On Jul 29, 6:56 pm, GuiGui



socket(), avec AF_INET (ou PF_INET), SOCK_STREAM et probablement 0 en protocol, c'est bien
ça ?

Parce que je ne vois pas de raisons de perdre des paquets en TCP.


Moi non plus.
Tout marche sans aucun probleme a 100 % en local sous Ethernet
(un LAN avec juste un routeur entre les deux machines)
les donnees envoyees sont toujours recues, et dans les deux sens,
alors pour moi ca valide le code de mon programme de com.

Par Internet ca fonctionne, mais il arrive, bien que ce
soit rare donc pas genant en pratique, que quelquefois des
donnees envoyees par send() ne soient pas recues (par recv)



Attention, il n'y a pas forcément un recv par send avec TCP.
Sur un lan, il est possible que les temps de réponses et propagations fassent que chaque
bloc survive à la traversé.
Au travers d'un réseau plus complexe, on peut avoir des comportements différents:
aggrégation de données retransmises, fermeture de fenêtres...
J'espère que tes données/messages sont correctement délimités dans le flux d'octets que tu
émets et reçoit.

Un truc quand même: la séquence "socket-bind-listen-accept" et "close" (d'ailleurs,
pourquoi closesocket ? normalement c'est close()... particularité windows que je ne
connais pas ?) n'a bien lieu qu'une seule fois, dans toute la vie de l'application,
n'est-ce pas ?
on n'est pas dans le cas d'un client qui ouvre une connexion pour chaque "message" a
traité, si ?

Et c'est lorsque j'ai constate cela que j'ai implemente un handshake
avec timeout et renvoi des donnees en cas de non-reception d'un ACK.



Et là, j'ai l'impression qu'au lieu d'attendre normalement la retransmission, ton appli
s'impatiente et court-circuite la marche normale (et c'est pas son boulot, c'est celui du
transport, en l'occurence TCP; Si tu as des besoins de réactivité, TCP n'est pas le bon
transport).
Et je m'interroge, comment l'autre coté gère la réception en double des messages ?

Bref, peux-tu détailler comment tu renvoies les données ?

Mais je ne m'y attendais pas du tout : j'ai toujours lu partout
que la couche TCP garantit que les donnees soient delivrees.
Des idees ?



Juste une angoisse: pour chaque "échange", ton architecture ouvre une nouvelle connexion.

Ou bien... tu ne regardes pas le retour de send().
Il renvoie le nombre d'octets envoyés.
Sur un Lan, il épuise difficilement la fenêtre de transmission, donc quand tu demandes à
envoyer 2000 octets, il réussit.
Au travers d'Internet... la fenêtre est beaucoup plus occupée (à cause du temps de
traversée), il peut donc n'en envoyer que 1700 (par exemple)... d'où des "paquets" qui te
manque à l'arrivée. En fait, ils ne sont jamais partis, et c'est ta faute.
send() t'a répondu 1700... c'était à toi de revenir plus tard pour les 300 restants.

Je m'étonne d'ailleurs que tu n'ai pas de select() dans tes fonctions. (ne serait-ce que
pour savoir quand il redevient possible d'écrire dans la socket, dont le buffer n'est
JAMAIS infini).



Un truc quand même, il faut bien penser à gérer par l'envoyeur le
timeout tcp et la fermeture de port coté réception.
Jean-Christophe
Le #19854111
On Jul 30, 1:03 am, Le Forgeron :

socket(), avec AF_INET (ou PF_INET), SOCK_STREAM et probablement 0 en pro tocol,
c'est bien ça ?



Oui, exactement. (+ de details a la fin de ce post)

Attention, il n'y a pas forcément un recv par send avec TCP.



Oui, quand j'envoie des donnees je boucle sur send()
et en reception c'est pareil pour recv().

Sur un lan, il est possible que les temps de réponses et propagations f assent que chaque
bloc survive à la traversé.
Au travers d'un réseau plus complexe, on peut avoir des comportements d ifférents:
aggrégation de données retransmises, fermeture de fenêtres...



Oui, je gere les messages de retour des fonctions socket. Mais il
semble bien que probleme soit du aux differences entre LAN et WAN.

J'espère que tes données/messages sont correctement
délimités dans le flux d'octets que tu émets et reçoit.
Un truc quand même: la séquence "socket-bind-listen-accept" et "close " (d'ailleurs,
pourquoi closesocket ? normalement c'est close()... particularité windo ws que je ne
connais pas ?) n'a bien lieu qu'une seule fois, dans toute la vie de l'ap plication,
n'est-ce pas ?



Attends : j'ai juste donne les noms des fonctions en vrac, pas leur
ordre
correct d'appel, ni leurs parametres, ni le traitement des valeurs de
retour.
Je vais mieux detailler le code a la fin de ce post.
BTW - je crois que winsock a ete calque sur les sockets Berkeley.

on n'est pas dans le cas d'un client qui ouvre une connexion pour chaque "message" a
traité, si ?
Et là, j'ai l'impression qu'au lieu d'attendre normalement la retransmi ssion, ton appli
s'impatiente et court-circuite la marche normale (et c'est pas son boulot , c'est celui du
transport, en l'occurence TCP; Si tu as des besoins de réactivité, TC P n'est pas le bon
transport).
Et je m'interroge, comment l'autre coté gère la réception en double des messages ?



En gros ca se passe comme ca :
A envoie un bloc de donnees vers B.
Si B recoit il renvoie "OK" vers A, qui envoie le bloc de donnees
suivant.
Si B ne recoit pas le timeout tombe en A, qui renvoie le meme bloc de
donnees.
Tout cela me donne une com a 100 % via internet.

Mais je dirais que peu importe cette gestion hand-shake/timeout/retry,
puisque le probleme n'est pas a ce niveau mais sur la couche juste au-
dessous.
Justement, je n'aurais pas eu a implementer ceci, si je ne perdais pas
de donnees.
Attention : je ne dis pas que le transport ne marche pas, c'est
sans doute mon soft qui ne fait pas ce qu'il faut, mais je n'arrive
pas a reproduire en LAN le defaut qui apparait en WAN.

Bref, peux-tu détailler comment tu renvoies les données ?



Ok, le code est a la fin de ce post.

Juste une angoisse: pour chaque "échange", ton architecture ouvre une n ouvelle connexion.
Ou bien... tu ne regardes pas le retour de send().



Bien sur que si, sinon comment gerer les codes d'erreurs, et
comment savoir combien d'octets ont ete effectivement envoyes.

Il renvoie le nombre d'octets envoyés.
Sur un Lan, il épuise difficilement la fenêtre de transmission,
donc quand tu demandes à envoyer 2000 octets, il réussit.
Au travers d'Internet... la fenêtre est beaucoup plus occupée (à ca use du temps de
traversée), il peut donc n'en envoyer que 1700 (par exemple)... d'où des "paquets" qui te
manque à l'arrivée.



Oui je sais cela, je lis la valeur de retour de send() pour traiter
les codes
d'erreurs, et si c'est ok pour deplacer le pointeur sur les donnees a
envoyer.

En fait, ils ne sont jamais partis, et c'est ta faute.
send() t'a répondu 1700... c'était à toi de revenir plus tard pour les 300 restants.



C'est bien ce que je fais : je boucle tant que tout n'est pas parti.

Je m'étonne d'ailleurs que tu n'ai pas de select() dans tes fonctions. (ne serait-ce que
pour savoir quand il redevient possible d'écrire dans la socket, dont l e buffer n'est
JAMAIS infini).



Interessant : il faudrait que tu me detailles l'emploi de select();

Mais je sais bien que le buffer n'est JAMAIS infini, et je lis bien
la
valeur de retour de send() pour recuperer le nombre d'octets envoyes.

Exemple : j'ai ecrit une fonction qui appelle un serveur HTTP,
recupere une page web et la parse pour en extraire des infos :
bien que la taille de la page soit superieure a celle de mon buffer,
tout ca fonctionne tres bien sur WAN (et donc je suis bien en TCP)
et puisque ca discute dans les deux sens, les send() et recv()
sont correctement appeles ... ou bien ?

Autre exemple : avec mon prog, par internet j'ai deja envoye
des fichiers de 10 Mo par blocs de 60 Ko et ca se passe bien ...
sauf que, quelques *tres rares* fois, il y a des blocs de donnees qui
ne sont pas recus, et dans ce cas : timeout, retry, et ca remarche.

J'ai bien tente de diminuer la taille des blocs jusqu'a 1 Ko,
mais le probleme est toujours present. J'ai aussi ajoute des
tempos dans la boucle d'emission pour ne pas charger le reseau,
jusqu'a 250 ms par bloc, mais ca n'ameliore rien non plus.

Ci-dessous les fonctions d'emission et de reception,
j'espere que ce sera assez lisible :-)

- Merci pour ton aide et ta patience -




/*--------------------------------------------------------------
Fonction d'emission
*ptr : pointeur sur les donnees
len : taille des donnees
--------------------------------------------------------------*/
int fSendBuffer(char *ptr, int len)
{
int nb; // util

// sock
if( fSetTxSock(1) ) // ouverture
return 1; // fatal error

// send loop
while( len > 0 )
{
// envoi du bloc courant
nb = send(ServParam.tx_socket,ptr,len,0); // envoi

// check
if( nb == SOCKET_ERROR ) // erreur
{
fSetTxSock(0); // on ferme
return 2; // fatal error
}

// next block
len -= nb; // decomptage de la quantite de donnees restantes
ptr += nb; // pointeur sur le bloc de donnees suivant
Sleep(1); // thread pause : one millisecond
}

// close
fSetTxSock(0); // fermeture
return 0; // ok
}




/*--------------------------------------------------------------
Fonction de reception (tourne dans sa propre thread)
1. Etablissement de la connection TCP
2. Boucle de reception
3. Traitement des donnees recues + reponse eventuelle

strucNet *N : structure avec les [IP:port] des deux PC
RxBuf : buffer de reception
iNbRxBuf : nombre d'octets recus dans le buffer de reception
LOCBUFFERSIZE : taille du buffer de reception
--------------------------------------------------------------*/
int fListen( strucNet *N )
{
int iNbTxBuf = 0, // nombre d'octets a envoyer
iNbRxBuf = 0, // nombre d'octets recus
fromlen, // util
nb; // util

struct sockaddr_in
local, // local addr
from; // distant addr

// init
fromlen = sizeof(from);
local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr(N->ip_local);
local.sin_port = htons(N->port);

// sock
N->listen_socket = socket(local.sin_family,SOCK_STREAM,0);

if (N->listen_socket == INVALID_SOCKET)
return -1; // fatal error

// bind
if( SOCKET_ERROR == bind(N->listen_socket,(struct sockaddr*)
&local,sizeof(local)) )
return -2; // fatal error

// listen
if( SOCKET_ERROR == listen(N->listen_socket,5) )
return -3; // fatal error

// *** listening loop ***

while( uOption & OPT_SERVRUNNING )
{
// accept (bloquant)
N->msgsock = accept(N->listen_socket,(struct sockaddr*)&from,
&fromlen);

if (N->msgsock == INVALID_SOCKET)
{
closesocket(N->msgsock);
return -4; // fatal error
}

// boucle de reception
for( iNbRxBuf=0, nb=1; (nb!=0) && (iNbRxBuf <
LOCBUFFERSIZE-1); )
{
// reception et concatenation du bloc courant a l'offset en
cours
nb = recv( N->msgsock, RxBuf+iNbRxBuf, LOCBUFFERSIZE-1-
iNbRxBuf, 0 );

if( nb == SOCKET_ERROR ) // oops
{
iNbRxBuf = nb; // on garde le code d'erreur
nb = 0; // on sort de la boucle de reception
}
else // okay
{
iNbRxBuf += nb; // decale l'offset de la taille du bloc recu
}
}
closesocket(N->msgsock); // done

//check
if( iNbRxBuf == SOCKET_ERROR )
continue; // error, on reboucle vers accept()

if( iNbRxBuf <= 0 )
continue; // pas de donnees, on reboucle vers accept()

// we have data
/* (snip code)
Ici on traite les donnees recues
Eventuellement on va renvoyer un message avec la fonction
fSendBuffer( *ptr, len ); // reply
*/

//loop : reboucle vers accept()
}

// clean up
closesocket(N->msgsock);
return 0; // ok
}


/*--------------------------------------------------------------
Open or Close - Appelee par la fonction d'emission
how = 1 : open
how = 0 : close
--------------------------------------------------------------*/
int fSetTxSock( int how )
{
static struct sockaddr_in so;
static SOCKET sock;

// close anyway
if( ServParam.tx_socket != INVALID_SOCKET ) // has not been closed
before
{
shutdown(ServParam.tx_socket,SD_SEND);
closesocket(ServParam.tx_socket);
ServParam.tx_socket = INVALID_SOCKET;
}

if( !how ) // we want to close it
return 0; // ok, it's done

// open
so.sin_family = AF_INET;
so.sin_addr.s_addr = inet_addr(ServParam.ip_distant);
so.sin_port = htons(ServParam.portdistant);
sock = socket(so.sin_family,SOCK_STREAM,0);

if( sock == INVALID_SOCKET )
return 1; // error

if( SOCKET_ERROR == connect(sock,(struct sockaddr*)&so,sizeof
(so)) )
{
closesocket(sock);
return 2; // error
}

// done
ServParam.tx_socket = sock;
return 0; // ok
}


// ENDS CODE //////////////////////////////////////////////////
Olivier Miakinen
Le #19855261
Bonjour,

Le 30/07/2009 13:50, Jean-Christophe répondait au Forgeron :

on n'est pas dans le cas d'un client qui ouvre une connexion pour chaque "message"
[à traiter], si ?
[...]



En gros ca se passe comme ca :
A envoie un bloc de donnees vers B.
Si B recoit il renvoie "OK" vers A, qui envoie le bloc de donnees
suivant.
Si B ne recoit pas le timeout tombe en A, qui renvoie le meme bloc de
donnees.
Tout cela me donne une com a 100 % via internet.



Pourtant, en regardant ton code il me semble bien que l'intuition
du Forgeron était bonne, et que tu ouvres et fermes la connexion
à chaque fois.

[...]

/*--------------------------------------------------------------
Fonction d'emission
*ptr : pointeur sur les donnees
len : taille des donnees
--------------------------------------------------------------*/
int fSendBuffer(char *ptr, int len)
{
int nb; // util

// sock
if( fSetTxSock(1) ) // ouverture
return 1; // fatal error



Donc en effet tu ouvres une nouvelle connexion à chaque fSendBuffer. Qui
plus est, tu commences par fermer la précédente : t'es-tu assuré que
tout avait été envoyé ?


// send loop
while( len > 0 )
{
// envoi du bloc courant
nb = send(ServParam.tx_socket,ptr,len,0); // envoi

// check
if( nb == SOCKET_ERROR ) // erreur



Je suppose que SOCKET_ERROR vaut -1. Personnellement j'ai l'habitude
d'écrire plutôt « (nb < 0) » que « (nb == -1) », mais d'après le man ça
devrait être équivalent.

{
fSetTxSock(0); // on ferme
return 2; // fatal error
}



Tu n'as pas vérifié le code contenu dans errno. Selon le cas cela
pourrait ne *pas* être une erreur fatale, par exemple EAGAIN ou
EWOULDBLOCK pour une socket non bloquante (ce qui ne semble pas être
le cas) ou encore EINTR si un signal a été reçu. Dans ce cas il faut
continuer à envoyer la suite.

Ah, une recherche dans MSDN m'indique que c'est WSAGetLastError() au
lieu de errno, WSAEWOULDBLOCK au lieu de EWOULDBLOCK et WSAEINTR au lieu
de EINTR, mais la remarque reste valable.

[...]



Cordialement,
--
Olivier Miakinen
Jean-Christophe
Le #19855751
On Jul 30, 3:49 pm, Olivier Miakinen :

Pourtant, en regardant ton code il me semble bien que l'intuition
du Forgeron était bonne, et que tu ouvres et fermes la connexion
à chaque fois.



Tu parles de l'appel a fSetTxSock(), comment
puis-je proceder sans l'etablir a chaque fois ?

Donc en effet tu ouvres une nouvelle connexion à chaque fSendBuffer. Qu i
plus est, tu commences par fermer la précédente : t'es-tu assuré qu e
tout avait été envoyé ?



Non, car je suppose que l'emission precedente est forcement
partie puisque je ne la termine que lorsque send() retourne zero.
La fermeture de socket ne se realise qu'en quittant fSendBuffer();
(doute : est-ce que ca se tient ?)

> if( nb == SOCKET_ERROR ) // erreur
Je suppose que SOCKET_ERROR vaut -1. Personnellement j'ai l'habitude
d'écrire plutôt « (nb < 0) » que « (nb == -1) », mais d'a près le man ça
devrait être équivalent.



Pour: "if(nb==SOCKET_ERROR)" j'ai suivi la doc winsock.

Tu n'as pas vérifié le code contenu dans errno. Selon le cas cela
pourrait ne *pas* être une erreur fatale, par exemple EAGAIN ou
EWOULDBLOCK pour une socket non bloquante (ce qui ne semble pas être
le cas)



Non, cette socket est bloquante, et je suppose que la fonction
send() ne rend la main qu'apres avoir envoye les donnees.
C'est pour cela que je boucle dessus pour envoyer
tous les blocs de donnees les uns apres les autres.

ou encore EINTR si un signal a été reçu.
Dans ce cas il faut continuer à envoyer la suite.



Que signifie le code INTR ?

Ah, une recherche dans MSDN m'indique que c'est WSAGetLastError() au
lieu de errno, WSAEWOULDBLOCK au lieu de EWOULDBLOCK et WSAEINTR au lieu
de EINTR, mais la remarque reste valable.



Ah, WSAEINTR, okay c'est note.

J'appelle bien WSAGetLastError() pour faire un report d'erreur
vers une fenetre d'affichage, je n'ai simplement pas recopie
tout le code ici pour ne pas alourdir le post.

D'apres toi il semble que le probleme se situe a l'emission ?
Et non a la reception : est-ce que fListen() te semble correct ?
Comment m'y prendre pour envoyer sans ouvrir une sock via fSetTxSock
() ?

Merci pour ton feedback.
Publicité
Poster une réponse
Anonyme