Problème réseau ! [C] - C++ - Programmation
Marsh Posté le 30-07-2002 à 15:49:12
Bigre !
J'utilise SOCK_STREAM et il me semblait que c'était du TCP/IP...
Je n'y comprend rien... j'ai juste renvoyé une valeur en retour et pouf ça marche...
Quelqu'un pourrait-il m'expliquer ?
Marsh Posté le 30-07-2002 à 15:55:51
BB138 a écrit a écrit : Je me suis fait un petit client / serveur. Le client se charge de récupérer l'affichage d'une fenêtre de le transmettre au serveur qui doit ensuite l'afficher. Lorsque j'exécute le client et le serveur sur la même machine il n'y a pas de problème mais dès qu'ils sont sur des machines différentes plus rien ne fonctionne correctement. Le serveur (d'après ce qu'il affiche) semble recevoir les données dans le désordre... De plus il semble qu'il reçoive plus de donnée que ce qui lui est normalement envoyé... J'utilise VC++ avec les fonction de base send() et recv(). Si vous avez une idée d'où cela pourrais provenir... Merci d'avance !!! |
Tu ferais pas de l'udp par hasard...
Marsh Posté le 30-07-2002 à 16:10:45
Et bien il ne me semble pas, j'initialise ma chausette avec :
socket(AF_INET, SOCK_STREAM, 0)
et normalement SOCK_STREAM c'est pour du TCP...
Marsh Posté le 30-07-2002 à 16:19:28
BB138 a écrit a écrit : Et bien il ne me semble pas, j'initialise ma chausette avec : socket(AF_INET, SOCK_STREAM, 0) et normalement SOCK_STREAM c'est pour du TCP... |
Yep, effectivement...
C'est quoi ta commande connect derriere?
Marsh Posté le 30-07-2002 à 16:38:54
Voilà mon connect :
connect(*talk_socket, (struct sockaddr*)addr_server, sockaddr_len);
avec :
sockaddr_len = sizeof(struct sockaddr_in);
*talk_socket est un paramètre de fonction,
addr_server a été rempli avec un pointeur sur une structure hostent
Marsh Posté le 30-07-2002 à 16:41:46
Citation : |
En fait, ça fonctionne un certain temps puis hop ça plante... comme ça sans crier gare !
Marsh Posté le 30-07-2002 à 17:13:49
un p'tit exemple:
m_s = socket (AF_INET, SOCK_STREAM, 0);
if (m_s == INVALID_SOCKET){
return -1;
}
err = connect (m_s, (PSOCKADDR) &(lnkTItemconnexion->TItem.DestAdr), sizeof(lnkTItemconnexion->TItem.DestAdr));
if (err == SOCKET_ERROR){
return -1;
}
Je sais pas si ça t'avance...
Marsh Posté le 30-07-2002 à 17:24:49
Ben j'ai a peu près la même chose ...
Code :
|
Marsh Posté le 30-07-2002 à 17:34:00
Si ça plante au bout d'un moment c peut être du à un pb d'alloc memoire inherent au traitement que tu fais...
Marsh Posté le 31-07-2002 à 08:45:22
Je ne crois pas car il y a les mêmes symptômes qu'avant : la fonction recv() ne semble pas être bloquante car je compte ce que j'envoie par le client et à l'arrivée j'ai plus de données !!!
Cela pourrait-il être un problème réseau indépendant de moi ?
Marsh Posté le 31-07-2002 à 09:44:00
BB138 a écrit a écrit : Je ne crois pas car il y a les mêmes symptômes qu'avant : la fonction recv() ne semble pas être bloquante car je compte ce que j'envoie par le client et à l'arrivée j'ai plus de données !!! Cela pourrait-il être un problème réseau indépendant de moi ? |
Oui, tu as raison pasque si ça fonctionne en local en plus....
Le recv, tu le met bloquant à combien de byte? pasque si il a pas le compte, il peut partir en timeout si celui est trop agressif....
Marsh Posté le 31-07-2002 à 10:33:27
BB138 a écrit a écrit : Euh, j'ai tout laissé par défaut... |
C'est quoi ton recv() ?
(mets ta ligne)
Marsh Posté le 31-07-2002 à 10:40:05
Voilà mon recv() :
Code :
|
Marsh Posté le 31-07-2002 à 10:45:00
BB138 a écrit a écrit : Voilà mon recv() :
|
Moi ce que je fais en général, c'est que j'envois un paquet de taille fixe specifiant la taille de ce qui suit. Je le lis avec la param de taille fixe ds le recv.
Ensuite je n'ai qu'a mettre en param du recv la taille attendue.
Là, j'ai l'impression que tu lis un peu comme ça arrive sur ta socket... mais je me trompe peut être!
Et status, il vaut quoi quand ça deconne? t'es sous quelle OS?
Marsh Posté le 31-07-2002 à 10:58:12
En fait si je ne met pas la taille reçu au préalable dans la fonction recv() c'est que généralament cette taille est en dehors de capacités disponible.
Sous windows 2000, sans modifier les valeurs par défaut, la taille maxi du buffer reçu ou envoyé est de 8192 octets ce qui n'est pas suffisant pour moi ! Du coup, je fais une petite boucle pour le client et le serveur qui récupère/envoie le maximum d'octets (8192) ou moins si on arrive vers la fin des donnée que je souhaite envoyer/recevoir d'où le data_remain.
Marsh Posté le 31-07-2002 à 11:01:18
J'oubliais, j'ai fait une petite modif pour vérifier justement que status était bien égal à size. C'est le cas pour les deux premiers tours de boucle mais ensuite ce n'est plus le cas...
Pourtant, j'envoie toujours les mêmes données (deux while imbriqués...
Marsh Posté le 31-07-2002 à 11:06:46
BB138 a écrit a écrit : J'oubliais, j'ai fait une petite modif pour vérifier justement que status était bien égal à size. C'est le cas pour les deux premiers tours de boucle mais ensuite ce n'est plus le cas... Pourtant, j'envoie toujours les mêmes données (deux while imbriqués... |
C'est que c'est un code d'erreur, faut le tester voir ce qu'il te dit.
Les codes de retour sont:
WSANOTINITIALISED A successful WSAStartup call must occur before using this function.
WSAENETDOWN The network subsystem has failed.
WSAEFAULT The buf parameter is not completely contained in a valid part of the user address space.
WSAENOTCONN The socket is not connected.
WSAEINTR The (blocking) call was canceled through SACancelBlockingCall.
WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.
WSAENETRESET The connection has been broken due to the keep-alive activity detecting a failure while the operation was in progress.
WSAENOTSOCK The descriptor is not a socket.
WSAEOPNOTSUPP MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations.
WSAESHUTDOWN The socket has been shut down; it is not possible to receive on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH.
WSAEWOULDBLOCK The socket is marked as nonblocking and the receive operation would block.
WSAEMSGSIZE The message was too large to fit into the specified buffer and was truncated.
WSAEINVAL The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled or (for byte stream sockets only) len was zero or negative.
WSAECONNABORTED The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no longer usable.
WSAETIMEDOUT The connection has been dropped because of a network failure or because the peer system failed to respond.
WSAECONNRESET The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket as it is no longer usable. On a UPD-datagram socket this error would indicate that a previous send operation resulted in an ICMP "Port Unreachable" message.
Un petit switch devrait nous aider à y voir plus clair...
Marsh Posté le 31-07-2002 à 11:26:39
En fait, j'ai déjà relevé les codes d'erreur qui sont :
WSAEINTR 10004
WSAEACCES 10013
WSAEFAULT 10014
WSAEINVAL 10022
WSAEWOULDBLOCK 10035
WSAEINPROGRESS 10036
WSAENOTSOCK 10038
WSAEMSGSIZE 10040
WSAEOPNOTSUPP 10045
WSAENETDOWN 10050
WSAENETRESET 10052
WSAECONNABORTED 10053
WSAECONNRESET 10054
WSAENOBUFS 10055
WSAENOTCONN 10057
WSAESHUTDOWN 10058
WSAETIMEDOUT 10060
WSAEHOSTUNREACH 10065
WSANOTINITIALISED 10093
(rangé par ordre croissant des valeurs correspondantes)
Mais status me renvoie des valeurs variables de 5000 a 8000 généralement...
et en fait il est censé renvoyer un SOCKET_ERROR (valeur = -1), les autres erreurs sont récupérées à l'aide de WSAGetLastError()...
Marsh Posté le 31-07-2002 à 11:29:42
Bon ben faut passer par un select pour voir ce qui est dispo en taille.
C'est marrant pasqu'il te renvoit bien la taille...
Marsh Posté le 31-07-2002 à 12:03:56
C'est à dire que normalement il ne devrait pas y avoir de soucis... mais en fait ma boucle de send() tourne jusqu'à 'saturer' (c'est ce qui me semble) la file d'attente et lorsque de l'autre côté il y a un recv(), il ne prend pas les données du send() qu'il devrait (là encore c'est ce qui me semble)...
Marsh Posté le 31-07-2002 à 14:29:29
Mmmmhh... Dans ce cas, qu'a tu commes valeurs retour du send?
Il se peut que tu ais un WSAENOBUFS comme erreur... (Tu n'as plus de buffer dispo pour envoi)
ex:
Client>J'envois X bytes (1)
Serveur>je Reçois X bytes (1)
Client>J'envois X bytes (2)
Serveur>je ne suis pas rebloqué sur le recv...
Client>J'envois X bytes (3)
Serveur>je ne suis toujours pas rebloqué sur le recv...
Client>J'envois X bytes -> Le buffer d'envoi est depassé!
Serveur>je me bloque sur le receive
Client>J'envois X bytes (4)
Serveur>Je recois (4)
donc coté client tu as envoyé 1,2,3 et 4
coté serveur tu as reçu 1 et 4
Marsh Posté le 31-07-2002 à 15:18:14
Mais normalement en TCP/IP ne devrait-il pas conserver l'ordre ?
Et puis il doit y avoir un autre problème, je m'explique :
Voilà ma nouvelle formule...
Serveur>J'envoie X bytes (1)
Client>Je reçois X bytes (1)
Client>J'envoie 1 byte (a)
Serveur>Je reçois 1 byte (a)
Serveur>J'envoie X bytes (2)
Client>Je reçois X bytes (2)
Client>J'envoie 1 byte (b)
Serveur>Je reçois 1 byte (b)
...
et normalement comme ça il n'y a pas de problème ...
En fait, il y en a tout de même un car quand je lance le client et le serveur ils "dialoguent" correctement pendant un moment variable (j'ai regardé combien de fois la boucle était parcourue) puis zou une erreur la taille de status (dans status = recv (...) ) ne correspond plus...
Marsh Posté le 31-07-2002 à 15:21:23
Si ça continue je vais être obligé de faire plein de contrôle dans tous les sens... mais j'ai un peu peur que ce soit indépendant de ma volonté...
Marsh Posté le 31-07-2002 à 15:25:01
Bizarre tout de meme...
Recapepetons:
1) tu envois X bytes, puis 1 byte, ca marche
2) au bout d'un moment, tu ne recois pas X, mais Y bytes (avec Y<X)
3) apres que se passe t'il?
Est ce que X est bien toujours le même (si j'ai bien compris...)?
Si X n'est pas tjrs le même, n'essais tu pas d'envoyer plus de bytes que le nb maximal (SO_MAX_MSG_SIZE)?
Le pb c'est que les fct send et recv ne retournent plus le même nb au bout d'un moment, c'est ça?
Marsh Posté le 31-07-2002 à 15:45:42
X n'est pas toujours le même mais le plus souvent égal 8192 (valeur max par défaut que le client/serveur peut recevoir/envoyer) cette valeur est récupérée à l'aide de getsockopt()
Je viens de faire un petit test :
-voilà ce qui est envoyé
acqWnd->lenZ 23585 (taille totale à envoyer via la boucle suivante)
8192 8192 7201 (taille des 'morceaux' envoyés)
acqWnd->lenZ 23659
8192 8192 7275
acqWnd->lenZ 23450
8192 8192 7066
acqWnd->lenZ 22963
8192
-voilà ce qui est reçu
data_length 23585 (taille totale à recevoir dans la boucle suivante)
8192 8192 7201 (taille des 'morceaux" reçus)
data_length 23659
8192 8192 7275
data_length 23450
8192 8192 7066
data_length 22963
--> et là erreur !!! la taille du 'morceau' reçu est de 2920 alors que la taille attendue est de 8192...
Je ne vois vraiment pas d'où cela peut venir
Marsh Posté le 31-07-2002 à 15:53:17
Il doit y avoir une erreur si le recv se debloque sans avoir reçu le total!!!
T'as rien comme erreur à ce moment là?
Marsh Posté le 31-07-2002 à 16:12:13
Il ne me donne pas d'erreur... il saute le test qui est sur la ligne suivante du recv(...) (if (status == SOCKET_ERROR))...
Par contre, j'ai une bonne nouvelle si je lui indique que la taille maximum des données à faire transiter inférieure à la taille par défaut ça marche !!!
Depuis quelques minutes ça tourne avec une valeur de 1024 au lieu de 8192...
Si j'arrive à mieux je te fais signe.
Marsh Posté le 31-07-2002 à 16:48:02
BB138 a écrit a écrit : Il ne me donne pas d'erreur... il saute le test qui est sur la ligne suivante du recv(...) (if (status == SOCKET_ERROR))... Par contre, j'ai une bonne nouvelle si je lui indique que la taille maximum des données à faire transiter inférieure à la taille par défaut ça marche !!! Depuis quelques minutes ça tourne avec une valeur de 1024 au lieu de 8192... Si j'arrive à mieux je te fais signe. |
De toutes façon, c'est pas mal de pas avoir des paquets trop gros car tu minimise le risque d'erreur.
Marsh Posté le 31-07-2002 à 17:27:44
Même en me déconnectant du réseau global et en ne connectant que deux machines entre elles une valeur de 8192 ou 4096 est encore trop importante et fait tout planter ou bout d'un certain temps... Par contre avec 2048 ça semble bien aller !
En tout cas merci beaucoup pour ton aide c'était vraiment très gentil !
Je ne regrette juste d'avoir perdu autant de temps sur ce satané problème...
Marsh Posté le 31-07-2002 à 17:31:09
BB138 a écrit a écrit : Même en me déconnectant du réseau global et en ne connectant que deux machines entre elles une valeur de 8192 ou 4096 est encore trop importante et fait tout planter ou bout d'un certain temps... Par contre avec 2048 ça semble bien aller ! En tout cas merci beaucoup pour ton aide c'était vraiment très gentil ! Je ne regrette juste d'avoir perdu autant de temps sur ce satané problème... |
a mon avis y dois y avoir une mouise avec winsock...
J'ai verifié, je montais pas au dessuis de 2Ko/envoi dans mes progs...
Bonne chance!
Marsh Posté le 01-08-2002 à 10:25:02
Bon, j'en refous une couche...
Tu as quoi comme valeurs par defaut dans SO_RCVBUF et SO_SNDBUF?
(option de setsockopt)
Marsh Posté le 01-08-2002 à 10:39:41
J'ai 8192 aussi bien en réception qu'en envoi, et ce, pour le serveur et le client !
Marsh Posté le 01-08-2002 à 10:45:23
BB138 a écrit a écrit : J'ai 8192 aussi bien en réception qu'en envoi, et ce, pour le serveur et le client ! |
zut!
Marsh Posté le 30-07-2002 à 15:39:02
Je me suis fait un petit client / serveur. Le client se charge de récupérer l'affichage d'une fenêtre de le transmettre au serveur qui doit ensuite l'afficher.
Lorsque j'exécute le client et le serveur sur la même machine il n'y a pas de problème mais dès qu'ils sont sur des machines différentes plus rien ne fonctionne correctement.
Le serveur (d'après ce qu'il affiche) semble recevoir les données dans le désordre... De plus il semble qu'il reçoive plus de donnée que ce qui lui est normalement envoyé...
J'utilise VC++ avec les fonction de base send() et recv().
Si vous avez une idée d'où cela pourrais provenir...
Merci d'avance !!!