[C/C++] Problème - Socket / Adresse IP

Problème - Socket / Adresse IP [C/C++] - C++ - Programmation

Marsh Posté le 01-01-2008 à 22:18:34    

Bonjour,
 
J'ai dans le but de réaliser un échange de données tout simple (client/serveur) en tcp/ip. Pour l'instant, le serveur stocke du texte en mémoire avec un char[], et quand le client se connecte, le serveur le lui envoie..
 
Afin de vous épargner une lecture inutile, mon code marche (du moins je croit). Le problème ne viend apparemment pas de là c'est pourquoi je vous conseille de ne pas le lire et de passer à la suite.
 
Serveur:
 

Code :
  1. #if defined (WIN32)
  2. #include <winsock2.h>
  3. #elif defined (linux)
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <unistd.h>
  9. #define INVALID_SOCKET -1
  10. #define SOCKET_ERROR -1
  11. #define closesocket(s) close (s)
  12. typedef int SOCKET;
  13. typedef struct sockaddr_in SOCKADDR_IN;
  14. typedef struct sockaddr SOCKADDR;
  15. #endif
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. int main (void)
  19. {
  20.     #if defined (WIN32)
  21.         WSADATA WSAData;
  22.         int erreur = WSAStartup(MAKEWORD(2,0), &WSAData);
  23.     #else
  24.         int erreur = 0;
  25.     #endif
  26.     SOCKET sock;
  27.     SOCKADDR_IN sin;
  28.     SOCKET csock;
  29.     SOCKADDR_IN csin;
  30.     char buffer[512] = "Bonjour !";
  31.     int recsize = (int) sizeof csin;
  32.     int sock_err;
  33.     // Si les sockets Windows fonctionnent
  34.     if(!erreur)
  35.     {
  36.         sock = socket (AF_INET, SOCK_STREAM, 0);
  37.         // Si la socket est valide
  38.         if (sock != INVALID_SOCKET)
  39.         {
  40.             printf ("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
  41.             // Configuration
  42.             sin.sin_addr.s_addr    = INADDR_ANY;/*htonl (INADDR_ANY);*/ // Adresse IP automatique
  43.             sin.sin_family         = AF_INET;              // protocole familial (IP)
  44.             sin.sin_port           = htons (21235);       // listage du port
  45.             sock_err = bind (sock, (LPSOCKADDR) &sin, sizeof sin);
  46.             //Si la socket fonctionne
  47.             if (sock_err != SOCKET_ERROR)
  48.             {
  49.                 // démarrage de l'écoute (listage) (mode server)
  50.                 sock_err = listen (sock, 5);
  51.                 printf ("Ecoute du port %d...en cours..\n", 21235);
  52.                 //Si la socket fonctionne
  53.                 if (sock_err != SOCKET_ERROR)
  54.                 {
  55.                     // Attente pendant laquelle le client se connecte
  56.                     printf ("Patientez pendant que le client se connecte sur le port %d...\n", 21235);
  57.                  //   csin.sin_addr.s_addr    = htonl(INADDR_ANY);
  58.                //     csin.sin_family         = AF_INET;
  59.                  csock = accept (sock, NULL, NULL);//   csock = accept (sock, (SOCKADDR *) &csin, &recsize);
  60.                  if (csock==INVALID_SOCKET)exit(1);
  61.                     printf ("Un client se connecte avec la socket %d de %s:%d\n", csock, inet_ntoa (csin.sin_addr), 21235);
  62.                     sock_err = send(csock, buffer, sizeof(buffer), 0);
  63.                     if (sock_err != SOCKET_ERROR)
  64.                         printf("Chaine envoyée : %s\n", buffer);
  65.                     else
  66.                         printf("Erreur de transmission\n" );
  67.                     //Il ne faut pas oublier de rompre la connexion (fermée dans les deux sens)
  68.                     shutdown (csock, 2);
  69.                 }
  70.             }
  71.             // fermeture de la socket
  72.             printf ("Fermeture de la socket...\n" );
  73.             sock_err = closesocket(sock);
  74.             printf ("Fermeture du serveur terminee\n" );
  75.         }
  76.         #if defined (WIN32)
  77.             WSACleanup();
  78.         #endif
  79.     }
  80.     // On attend que l'utilisateur tape sur une touche, puis on ferme
  81.     getchar();
  82.     return EXIT_SUCCESS;
  83. }


Client:
 

Code :
  1. #if defined (WIN32)
  2. #include <winsock2.h>
  3. #elif defined (linux)
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <unistd.h>
  9. #define INVALID_SOCKET -1
  10. #define SOCKET_ERROR -1
  11. #define closesocket(s) close (s)
  12. typedef int SOCKET;
  13. typedef struct sockaddr_in SOCKADDR_IN;
  14. typedef struct sockaddr SOCKADDR;
  15. #endif
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. // Pour utiliser les objets string!
  19. //#include <iostream>
  20. //#include <string> // Obligatoire pour pouvoir utiliser les objets string
  21. //using namespace std;
  22. // Pour utiliser les objets string!
  23. int main (void)
  24. {
  25.     #if defined (WIN32)
  26.         WSADATA WSAData;
  27.         int erreur = WSAStartup(MAKEWORD(2,0), &WSAData);
  28.     #else
  29.         int erreur = 0;
  30.     #endif
  31.     SOCKET sock;
  32.     SOCKADDR_IN sin;
  33.     char buffer[512];//Création du tableau de char qui recevra celui du serveur
  34.     // Si les sockets Windows fonctionnent
  35.     if(!erreur)
  36.     {
  37.         // Création de la socket
  38.         sock = socket(AF_INET, SOCK_STREAM, 0);
  39.         // Configuration de la connexion
  40.         sin.sin_addr.s_addr = inet_addr("192.168.1.22" );
  41.         sin.sin_family = AF_INET;
  42.         sin.sin_port = htons(21235);
  43.         // Si l'on a réussi à se connecter
  44.         if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
  45.         {
  46.             printf("Connection à %s sur le port %d\n", inet_ntoa(sin.sin_addr), 21235);
  47.             // Si l'on reçoit des informations : on les affiche à l'écran
  48.             if(recv(sock, buffer, sizeof(buffer), 0) != SOCKET_ERROR)
  49.             printf("recu: %s", buffer);
  50.             printf("\n" );
  51.         }
  52.         // sinon, on affiche "Impossible de se connecter"
  53.         else
  54.         {
  55.             printf("Impossible de se connecter\n" );
  56.         }
  57.         // On ferme la socket
  58.         closesocket(sock);
  59.         #if defined (WIN32)
  60.             WSACleanup();
  61.         #endif
  62.     }
  63.     // On attend que l'utilisateur tape sur une touche, puis on ferme
  64.     system("PAUSE" );
  65.     return EXIT_SUCCESS;
  66. }


 
Les deux codes (client et serveur) fonctionnent en réseau local:
 
-192.168.1.22..OK
-127.0.0.1.......OK
 
http://img219.imageshack.us/img219/8553/95308523ql3.png
 
 
 
Par contre, quand je met mon ip publique (http://monip.org) ça foire:
 
 
http://img219.imageshack.us/img219/9778/82788808af4.png
 
Pour info, je possède une Neufbox NB4 et je tourne sous XP. J'ai fais une redirection du port 21235 vers mon pc:
(Je n'ai pas de firewall logiciel, juste avast comme anti-virus)
 
NAT:
 
http://img217.imageshack.us/img217/425/86598706vt6.png
 
Je comprend pas pourquoi ça fonctionne pas.. (même si c'est le cas en local) parce que l'objectif pour moi, c'est quand même que ça marche sur deux machine via internet... J'espère que vous pourrez m'aider, j'en serai super content!  :lol:  
 
PS: J'ai peut-être une piste, lorsque je me connecte avec l'ip publique sur le port fowardé (21235), même si je ne reçoit pas le paquet du serveur, j'ai l'impression qu'il détecte que je me suit connecté sur son socket (cf : screen) et tente de me l'envoyer, malheuresement ça coince et le client ne le reçoit pas..Bref si ça peut vous aider.
 
Merci de votre écoute :p

Reply

Marsh Posté le 01-01-2008 à 22:18:34   

Reply

Marsh Posté le 02-01-2008 à 11:01:10    

il ne manque pas un gethostbyname() dans le client?

Reply

Marsh Posté le 02-01-2008 à 20:02:04    

Je suis pas expert mais je croit pas que ça vienne de là, d'après ce que j'ai pu voir les fonctions genre gethostbyname(), gethostname()... servent à obtenir des infos sur le nom de domaine. Afin de pouvoir me connecter, je croit pas que ça me soit utile, je pense que seule l'ip et le port suffisent. Etant donné qu'à la base je connait l'ip du serveur, je devrai pas avoir besoin de manipuler le nom d'hote (sauf si je me connecte grâce a un DNS). Autre chose, j'ai oublié de préciser que pour l'instant j'ai réalisé mes tests chez moi en essayant de me connecter à ma propre ip publique.. c'est peut-être pour ça que ça ne fonctionne pas.. Je veux dire, j'ai remarqué qu'en réseau local on a même pas besoin d'avoir plusieurs machines pour réaliser une reception de paquets sur un port.. je sait pas du tout par quel composants du matériel le courant passe mais si ça se trouve, c'est impossible de faire ça avec internet. Donc peut-être que si je teste maintenant avec un pc distant ça marchera..C'est possible? Ce que j'ai dit est cohérent?

Reply

Marsh Posté le 03-01-2008 à 19:09:10    

Problème résolu, du moins j'ai testé avec 2 machines distantes et ça fonctionne. Même si j'ai aucune idée de pourquoi ça marche pas sur son propre PC, suremment que c'est pas possible.. A moins que ça vienne de la ligne "shutdown (csock,2);" qui fait que le message est envoyé mais vu que le port se referme directement après, le client ne le reçois pas. Enfin bref si un jour ça peut aider quelqu'un, tant mieux. :)

Reply

Marsh Posté le 03-01-2008 à 22:07:59    

Est-ce que t'arrives a pinger ton adresse IP publique depuis l'interieur ?

Reply

Marsh Posté le 03-01-2008 à 23:01:13    

Je crois ouai, quand je tape dans la console:
 
ping [mon ip publique], ça envoie 4 paquets, je reçois les 4.

Reply

Marsh Posté le 07-10-2009 à 16:22:44    

Slt preque 2 ans après, j'ai exactement le meme probleme, sauf que j'ai tester avec un pote et sa march pas, Ange j'aimerai prendre contact avec toi: zestyr@hotmail.fr. Comme ta eu le mem prob tu pourrai m'aider.
Bon je met mais code meme si je suis sure qu'il sont juste:
 
Serveur:

Code :
  1. #include <winsock.h>
  2. void main()
  3. {
  4.    
  5. int portM = 50;   
  6. char buffer[1024];
  7.    
  8. WSADATA WSAData;
  9. WSAStartup(MAKEWORD(2,0),&WSAData);
  10. SOCKET sock;
  11. SOCKET csock;
  12. SOCKADDR_IN sin;
  13. SOCKADDR_IN csin;
  14. sock = socket(AF_INET, SOCK_STREAM, 0);
  15. sin.sin_addr.s_addr   = htonl(INADDR_ANY);
  16. sin.sin_family    = AF_INET;
  17. sin.sin_port    = htons(50);
  18. bind(sock, (SOCKADDR *)&sin, sizeof(sin));
  19. listen(sock, 0);
  20.         while(1)
  21.  {
  22.   int sinsize = sizeof(csin);
  23.   if((csock = accept(sock,(SOCKADDR *)&csin,&sinsize)) != INVALID_SOCKET)
  24.   {
  25.             send(csock,"conexion: reussie",50,0);
  26.                       printf("\nIl y a un client\n" );
  27.   }
  28.  while(1)
  29.  {
  30.             printf("\nenvoyer>" );
  31.   scanf("%s", buffer);
  32.             if(buffer != "" && buffer != "none" )
  33.   {
  34.              send(csock,buffer,50,0);
  35.              printf("\nenvoye>%s", buffer);       
  36.             }
  37.            
  38.         }
  39.         }
  40.        
  41. closesocket(sock);
  42. WSACleanup();
  43. }


 
Client:
 

Code :
  1. #include <stdio.h>
  2. #include <winsock.h>
  3. void main()
  4. {
  5. char Ip[8];   
  6. int Port;
  7. printf("\nconexion a: " );
  8. scanf("%s",Ip);
  9. printf("\npar le port: " );
  10. scanf("%d",&Port);   
  11.    
  12. char buffer[1024]= "conexion en cours...";
  13. WSADATA WSAData;
  14. WSAStartup(MAKEWORD(2,0),&WSAData);
  15.    
  16. SOCKET sock;
  17. sock = socket(AF_INET,SOCK_STREAM,0);
  18.    
  19. SOCKADDR_IN sin;
  20. sin.sin_addr.s_addr = inet_addr(Ip);
  21. sin.sin_family      = AF_INET;
  22. sin.sin_port        = htons(Port);
  23. while(1)
  24. {
  25. connect(sock,(SOCKADDR *)&sin,sizeof(sin));
  26.     int i = recv(sock,buffer,sizeof(buffer),0);
  27.     if (i)
  28.     {
  29.     printf("\nmessage> " );
  30.     printf(buffer);
  31.     }
  32. }
  33. closesocket(sock);
  34. WSACleanup();
  35. getchar();
  36. }



Message édité par Zestyr le 07-10-2009 à 16:24:22
Reply

Marsh Posté le 07-10-2009 à 17:34:58    

Tu dois rediriger les ports dans ta box, quand ce sera fait, ça fonctionnera en local avec ton ip 192.168.1.x et ta boucle locale (127.0.0.1). Quant à effectuer un test avec un connexion extérieure, tu ne peux le faire qu'avec une autre machine (extérieure à ton réseau local et via internet donc), parce que tu peux pas le faire à partir de ton pc même si tu passe par un proxy (c'est comme ça). Si rien de tout ça ne fonctionne pour l'instant, c'est tout simplement sois que tu n'a pas redirigé correctement le port sur lequel ton pc écoute(au niveau du routeur /box adsl), sois qu'un firewall bloque la connexion.

Reply

Sujets relatifs:

Leave a Replay

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