[C/C++] Sockets en UDP, problème d'envoi à une IP

Sockets en UDP, problème d'envoi à une IP [C/C++] - C++ - Programmation

Marsh Posté le 01-05-2003 à 09:35:23    

Salut,
 
Je me heurte actuellement à un problème étrange, je n'arrive pas à envoyer avec sendto (udp):
 

Code :
  1. SOCKET s;
  2. SOCKADDR_IN localaddr, useraddr, tempaddr;
  3. int addrsize;
  4. s = socket(AF_INET, SOCK_DGRAM, 0);
  5. addrsize = sizeof(SOCKADDR_IN);
  6. localaddr.sin_family = AF_INET;
  7. localaddr.sin_addr.s_addr = INADDR_ANY;
  8. localaddr.sin_port = htons(5000);
  9. bind(s, (LPSOCKADDR)&localaddr, sizeof(localaddr));
  10. tempaddr.sin_family = AF_INET;
  11. tempaddr.sin_port = htons(5000);
  12. r = recvfrom(s, buf, sizeof(buf), 0, (LPSOCKADDR)&useraddr, &addrsize);
  13. ...
  14. //ce sendto marche (useraddr est "rempli" par le recvfrom precedent
  15. sendto(s, "test", 4, 0, (LPSOCKADDR)&useraddr, addrsize);
  16. //par contre quand je rempli moi même pour envoyer à une ip précise et bien le telnet sur cette ip ne reçoit rien...
  17. tempaddr.sin_addr.s_addr = inet_addr("192.168.0.246" );
  18. sendto(s, "test", 4, 0, (LPSOCKADDR)&tempaddr, addrsize);


 
par contre le telnet sur cette ip peut lui envoyer au serveur sans problème (

Code :
  1. s = socket(AF_INET, SOCK_DGRAM, 0);
  2. localaddr.sin_family = AF_INET;
  3. localaddr.sin_addr.s_addr = inet_addr("192.168.0.1" );
  4. localaddr.sin_port = htons(5000);
  5. bind(s, (LPSOCKADDR)&localaddr, sizeof(localaddr));
  6. size = sizeof(localaddr);
  7. sendto(s, in, strlen(in), 0, (LPSOCKADDR)&localaddr, size);


 
je ne comprends pas...
merci
   ANT


Message édité par antsite le 01-05-2003 à 21:37:30
Reply

Marsh Posté le 01-05-2003 à 09:35:23   

Reply

Marsh Posté le 01-05-2003 à 10:28:20    

Faut-il une socket par IP (toujours en UDP biensur) ? J'ai un doute...

Reply

Marsh Posté le 01-05-2003 à 13:50:44    

Je comprends pas pourquoi tu parles de telnet et d'UDP ?
C'est pas du TCP plutot ? [:figti]

Reply

Marsh Posté le 01-05-2003 à 14:37:53    

ANTSite a écrit :

Faut-il une socket par IP (toujours en UDP biensur) ? J'ai un doute...


 
une socket par ip+port. il te faut donc une 2eme socket et un 2eme bind.
 
par contre utiliser l'udp pour recevoir/envoyer sur une meme socket, moi j'eviterais, le tcp est un plus approprié.

Reply

Marsh Posté le 01-05-2003 à 15:43:50    

t'as juste besoin d'un socket par bind, et un bind par port que t'ecoute;
en emission, tu peux envoyer vers autant d'ip:port que tu veux avec le meme socket

Reply

Marsh Posté le 01-05-2003 à 15:46:28    

Deaddy a écrit :

t'as juste besoin d'un socket par bind, et un bind par port que t'ecoute;
en emission, tu peux envoyer vers autant d'ip:port que tu veux avec le meme socket
 


 
Comment envoyer à plusieurs IP (cf mon code)
thx

Reply

Marsh Posté le 01-05-2003 à 16:35:34    

ANTSite a écrit :

Comment envoyer à plusieurs IP (cf mon code)
thx

En changeant les infos se trouvant dans le : (LPSOCKADDR)&useraddr :)  
 
Mais je vois pas comment tu comptes vérifier que le 2ème PC reçoit bien les infos. Pas avec telnet en tout cas :heink:

Reply

Marsh Posté le 01-05-2003 à 16:50:31    

c'est exactement ce que je fais (cf code!) et le telnet c'est pas le telnet tcp windows mais un telnet perso, un client udp tout simple

Reply

Marsh Posté le 01-05-2003 à 16:56:34    

Deaddy a écrit :

t'as juste besoin d'un socket par bind, et un bind par port que t'ecoute;
en emission, tu peux envoyer vers autant d'ip:port que tu veux avec le meme socket
 


 

Konar a écrit :


une socket par ip+port. il te faut donc une 2eme socket et un 2eme bind.


 
 
Qui a raison ?

Reply

Marsh Posté le 01-05-2003 à 17:11:49    

ANTSite a écrit :

c'est exactement ce que je fais (cf code!) et le telnet c'est pas le telnet tcp windows mais un telnet perso, un client udp tout simple

Là d'accord :)  
 
une socket UDP écoute sur un port. Elle ne peut donc recevoir des messages que sur ce port, mais pouvant provenir d'adresses sources différentes. De même, elle peut aussi émettre vers différentes adresses.

Reply

Marsh Posté le 01-05-2003 à 17:11:49   

Reply

Marsh Posté le 01-05-2003 à 18:08:56    

ANTSite a écrit :


 
Qui a raison ?


 
aucune idée, t'as ka tester et tu nous diras...

Reply

Marsh Posté le 01-05-2003 à 19:16:48    

Et bien c fait, c'est testé dans les 2 cas, je viens de créé une nouvelle socket exprès pour l'ip à laquelle je veux envoyer, je la crée comme dans mon code pour s, je la bind et paf le client à qui je veux envoyer reçoit toujours rien (testé avec 2 telnets (udp) un "pro" et un perso, pareil)...

Reply

Marsh Posté le 01-05-2003 à 19:19:51    

Peut être qu'il y a des champs mal initialisés. Reprends le useraddr qui marche, et réutilise le en changeant seulement l'IP de destination.

Reply

Marsh Posté le 01-05-2003 à 19:22:05    

C'est exactement ce que j'ai fait avec un memcpy et après j'ai fait tempaddr.sin_addr.s_addr = inet_addr("192.168.0.246" ); ben pareil  :sweat:  
Le problème est peut être ailleurs, si vous voulez plus de code (tout le code ?), demandez...

Reply

Marsh Posté le 01-05-2003 à 20:02:01    

ANTSite a écrit :

C'est exactement ce que j'ai fait avec un memcpy et après j'ai fait tempaddr.sin_addr.s_addr = inet_addr("192.168.0.246" ); ben pareil  :sweat:  
Le problème est peut être ailleurs, si vous voulez plus de code (tout le code ?), demandez...


 
au lieu d'un sendto(), essaye ca (en testant bien les valeurs de retour des fct, et si erreur fais un WSAGetLastError)
 

Code :
  1. SOCKET s = socket(AF_INET, SOCK_DGRAM ,0);
  2. if (connect(s, (struct sockaddr*)&server, sizeof server) == SOCKET_ERROR)
  3. {
  4.  OutputDebugString("error connect" );
  5.  return 1;
  6. }
  7. send(s, "test", 4, 0);


Reply

Marsh Posté le 01-05-2003 à 20:27:30    

Moi je veux bien mais je veux juste dire que je suis en UDP donc pas de connexion...
enfin bon j'ai fait un connect et y a pas d'erreur. Après le send je vois pas comment il pourrait marcher y a aucun destinataire d'indiqué nulle part... (contrairement à un sendto).

Reply

Marsh Posté le 01-05-2003 à 20:35:16    

ANTSite a écrit :

Moi je veux bien mais je veux juste dire que je suis en UDP donc pas de connexion...
enfin bon j'ai fait un connect et y a pas d'erreur. Après le send je vois pas comment il pourrait marcher y a aucun destinataire d'indiqué nulle part... (contrairement à un sendto).


 
arf... va falloir ke tu fasses plus de man que ca :
"
For a connectionless socket (for example, type SOCK_DGRAM), the operation performed by connect is merely to establish a default destination address that can be used on subsequent send/ WSASend and recv/ WSARecv calls.
"
 
le connect est justement la pour "indiquer le destinataire".
 
autre chose aussi : a moins d'une quelconque ratance au niveau du buffer dans le send, j'ai JAMAIS vu un send rater en udp.
(ca veut pas dire ke ca marche a tous les coups)
 
Pour ton truc d'envoyer des infos sur des ip differentes :
"
The default destination can be changed by simply calling connect again, even if the socket is already connected. Any datagrams queued for receipt are discarded if name is different from the previous connect.
"

Reply

Marsh Posté le 01-05-2003 à 20:40:35    

Ouh la très intéressant, j'ignorais complètement tout ça...
Donc faut-il banir les sendto au profit des send  & connect ?
 
P.S. : Connectionless avec emploi de connect... la je comprends toujours pas pourquoi ça s'appelle mode non connecté  :)


Message édité par antsite le 01-05-2003 à 20:43:20
Reply

Marsh Posté le 01-05-2003 à 20:47:02    

ANTSite a écrit :

Ouh la très intéressant, j'ignorais complètement tout ça...
Donc faut-il banir les sendto au profit des send  & connect ?
 
P.S. : Connectionless avec emploi de connect... la je comprends toujours pas pourquoi ça s'appelle mode non connecté  :)  


 
Pur le sendto je sais pas trop, je m'en suis jamais servi, c'est juste que j'ai jamais eu de pb avec les fct de base (socket, connect, send).
 
sinon je te le re-dis, si tu veux envoyer/recevoir en te servant de la meme socket, va plutot falloir songer a faire du tcp.

Reply

Marsh Posté le 01-05-2003 à 20:52:58    

sendto(s, "test", 4, 0, (LPSOCKADDR)&useraddr, addrsize);
 
je mettrai plutot
sendto(s, "test", 5, 0, (LPSOCKADDR)&useraddr, addrsize);
mais rien a voir avec la question, c'est juste que sinon il peux pas envoyer le '\0'

Reply

Marsh Posté le 01-05-2003 à 20:55:55    

ok donc, le deuxieme sendto tu l'envois sur le port 5000 de ton soit disant telnet, mais par simple curiosité, verifie le port sur lequel tu envoie le premier sendto ( celui qui est rempli par le recv ) je ne pense pas que ce soit 5000 mais un port attribué aléatoirement. ( le port de reception n'etant pas le port d'envoie )


Message édité par xWillow le 01-05-2003 à 20:56:55
Reply

Marsh Posté le 01-05-2003 à 20:57:02    

bon alors j'ai rajouté ça dans mon code
 
tempaddr.sin_addr.s_addr = inet_addr("192.168.0.246" );
SOCKET c = socket(AF_INET, SOCK_DGRAM, 0);
bind(c, (LPSOCKADDR)&tempaddr, addrsize);
connect(c, (LPSOCKADDR)&tempaddr, addrsize);
send(c, "test", 4, 0);
 
et bien le client n'a toujours rien
 
de plus j'ai aussi essayé ça (cf premier topic pour les variables,...)
tempaddr.sin_addr.s_addr = inet_addr("192.168.0.246" );
connect(s, (LPSOCKADDR)&tempaddr, addrsize);
send(s, "test", 4, 0);
 
et pareil (réemploi de la socket s et non une nouvelle comme c)

Reply

Marsh Posté le 01-05-2003 à 20:59:30    

quelle est le code du serveur sur la deuxieme ip ?

Reply

Marsh Posté le 01-05-2003 à 21:01:41    

xWillow a écrit :

ok donc, le deuxieme sendto tu l'envois sur le port 5000 de ton soit disant telnet, mais par simple curiosité, verifie le port sur lequel tu envoie le premier sendto ( celui qui est rempli par le recv ) je ne pense pas que ce soit 5000 mais un port attribué aléatoirement. ( le port de reception n'etant pas le port d'envoie )


 
cf premier post:
tempaddr.sin_family = AF_INET;  
tempaddr.sin_port = htons(5000);
 
edit: pardon j'avais pas compris ton post, mais alors comment faire pour envoyer à mon client si on ne connait pas le port ?
 
code du client "telnet":
la boucle de réception dans un thread

Code :
  1. while(!stop)
  2. {
  3.  strcpy(buf, "" );
  4.         r = recvfrom(s, buf, sizeof(buf), 0, 0, 0);
  5.  if(r == 0 || r == SOCKET_ERROR)
  6.   break;
  7.  buf[r] = '\0';
  8.         printf("- %s -\n", buf);
  9. }
  10. closesocket(s);


le main:
 

Code :
  1. s = socket(AF_INET, SOCK_DGRAM, 0);
  2. localaddr.sin_family = AF_INET;
  3. localaddr.sin_addr = inet_addr("192.168.0.1" );
  4. localaddr.sin_port = htons(5000);
  5. bind(s, (LPSOCKADDR)&localaddr, sizeof(localaddr));
  6. size = sizeof(localaddr);
  7. while(1)
  8. {
  9.         strcpy(in, "" );
  10.         gets(in);
  11.        
  12.         if(strcmp(in, "q" ) == 0) break;
  13.         else
  14.         {
  15.             printf("+ %s +\n", in);
  16.             sendto(s, in, sizeof(in), 0, (LPSOCKADDR)&localaddr, size);
  17.         }
  18. fflush(stdin);
  19. }


Message édité par antsite le 01-05-2003 à 21:23:07
Reply

Marsh Posté le 01-05-2003 à 21:03:43    

ce que je veux dire, c'est est ce que l'ip 192.168.0.246 attend bien sur le port 5000 ?

Reply

Marsh Posté le 01-05-2003 à 21:06:35    

je m'arrache un peu c'est rien
mais tu as pas besoin de faire de connect ni de faire plusieurs socket.

Reply

Marsh Posté le 01-05-2003 à 21:07:40    

ANTSite a écrit :

bon alors j'ai rajouté ça dans mon code
 
tempaddr.sin_addr.s_addr = inet_addr("192.168.0.246" );
SOCKET c = socket(AF_INET, SOCK_DGRAM, 0);
bind(c, (LPSOCKADDR)&tempaddr, addrsize);
connect(c, (LPSOCKADDR)&tempaddr, addrsize);
send(c, "test", 4, 0);
 
et bien le client n'a toujours rien
 
de plus j'ai aussi essayé ça (cf premier topic pour les variables,...)
tempaddr.sin_addr.s_addr = inet_addr("192.168.0.246" );
connect(s, (LPSOCKADDR)&tempaddr, addrsize);
send(s, "test", 4, 0);
 
et pareil (réemploi de la socket s et non une nouvelle comme c)


 
tu testerais bien toutes les valeurs de retour pour voir si y a pas d'erreur.
 
sinon, tu fais des closesocket() a des moments (serveur ou client) ? si oui faut refaire un appel a socket().
 
sinon la je vois pas trop, va ptet falloir que tu postes plus de code (si c pas trop gros)

Reply

Marsh Posté le 01-05-2003 à 21:08:18    

j'ai édité.
Alors dis moi comment faire car j'y crois moi qu'il n'y a pas besoin de connect et de plusieurs sockets !!

Reply

Marsh Posté le 01-05-2003 à 21:08:40    

je serai toi je reecrirai tout, je crois voir d'ou viens le probleme mais ca me fait chier de chercher =)

Reply

Marsh Posté le 01-05-2003 à 21:13:01    

Je crois pas non plus qu'il faille plusieurs sockets, ni de l'utilité du connect() ici [:figti]  
 
Essaie d'afficher le contenu de 'useraddr' et de 'tempaddr', pour essayer de voir où seraient les différences :/

Reply

Marsh Posté le 01-05-2003 à 21:16:08    

                         Serveur udp
                             /\
                            /  \
                           /    \  
                          /      \
                         /        \
                        /          \
                       /            \
                      /              \
                 Client1(udp)     Client2(udp)
 
 
Voila le probleme il y a client1 ki envoye "test" au server comment fdaire pour ke le server envoi au client2 "test" ?
 
si on poivait avoir une source simple ;)
 
merci

Reply

Marsh Posté le 01-05-2003 à 21:17:12    

Le code parce que je crois qu'il y a besoin:
tout ça est un thread
 

Code :
  1. SOCKADDR_IN localaddr, useraddr, tempaddr;
  2. s = socket(AF_INET, SOCK_DGRAM, 0);
  3. addrsize = sizeof(SOCKADDR_IN);
  4. localaddr.sin_family = AF_INET;
  5. localaddr.sin_addr.s_addr = INADDR_ANY;
  6. localaddr.sin_port = htons(5000);
  7. bind(s, (LPSOCKADDR)&localaddr, sizeof(localaddr));
  8. //Structure qui servira aux envois à toutes les IP//
  9. tempaddr.sin_family = AF_INET;
  10. tempaddr.sin_port = htons(5000);
  11. while(!r_stop)
  12. {
  13.         strcpy(buf, "" );
  14.         r = recvfrom(s, buf, sizeof(buf), 0, (LPSOCKADDR)&useraddr, &addrsize);
  15. if(r == 0 || r == SOCKET_ERROR)
  16.                break;
  17. buf[r] = '\0';
  18. if(strncmp(buf, "ttt", 3) == 0)
  19.              sendto(s, "ttt", 3, 0, (LPSOCKADDR)&useraddr, addrsize);
  20. else if(strncmp(buf, "yyy", 3) == 0)
  21. {
  22.              sendto(s, "yyy", 3, 0, (LPSOCKADDR)&useraddr, addrsize);
  23.                                                                
  24.              tempaddr.sin_addr.s_addr = inet_addr("192.168.0.246" );
  25.                  
  26.              sendto(s, "test", 4, 0, (LPSOCKADDR)&tempaddr, addrsize);
  27.         }
  28. }
  29. closesocket(s);


 
 
voila donc j'ai supprimé plein de trucs qui étaient superflus je pense et j'ai mis le code sans modif après les derniers posts (connect...)


Message édité par antsite le 01-05-2003 à 21:31:33
Reply

Marsh Posté le 01-05-2003 à 21:17:38    

je suis en train d'essayer de recoder pour voir :)

Reply

Marsh Posté le 01-05-2003 à 21:19:38    

dans tout tes sendto, quand tu mets la taille de l'envoie, tu mets juste le nombre de caractere, c'est pas correcte.
 il te manque la place pour envoyer le '\0', corrige stp =)

Reply

Marsh Posté le 01-05-2003 à 21:22:00    

r = recvfrom(s, buf, sizeof(buf), 0, (LPSOCKADDR)&useraddr, &addrsize);
 
c'est pas sizeof(buf) mais strlen(buf) :)

Reply

Marsh Posté le 01-05-2003 à 21:24:10    

xWillow a écrit :

r = recvfrom(s, buf, sizeof(buf), 0, (LPSOCKADDR)&useraddr, &addrsize);
 
c'est pas sizeof(buf) mais strlen(buf) :)


 
oui oui c'est noté.
Je pense pas que le problème soit là...  :)

Reply

Marsh Posté le 01-05-2003 à 21:24:44    

oui, je dit ca juste a titre informatif :o

Reply

Marsh Posté le 01-05-2003 à 21:26:51    

a mon avis, l'erreur viens du faite que tu binds avec un port des sockets qui ne le devraient pas, je suis en train de verifier

Reply

Marsh Posté le 01-05-2003 à 21:31:31    

si jamais le server envoye une info  o client k il vient d envoyer kelke chose ca marche nikel
comme ceci :

Code :
  1. bind(c, (LPSOCKADDR)&to, sizeof(to));
  2. sizePeerAddr = sizeof(SOCKADDR_IN);
  3. r = recvfrom(c, buf, sizeof(buf), 0, (LPSOCKADDR)&to, &sizePeerAddr);
  4. if(r == 0 || r == SOCKET_ERROR)
  5. printf("pb envoye" );
  6. sendto(c, "test", 4, 0, (LPSOCKADDR)&to, sizePeerAddr);


 
ce qui marche pas si c le client envoye "test" au server é ke le server doit envoyer "test" a un autre client  

Reply

Marsh Posté le 01-05-2003 à 21:33:34    

Ca marche quand la srtucture 'to' est rempli par la fonction recvfrom(), mais pas quand celle ci est initialisée directement [:gratgrat]


Message édité par mrbebert le 01-05-2003 à 21:34:00
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed