Communication programmes C

Communication programmes C - C - Programmation

Marsh Posté le 29-11-2011 à 16:56:02    

Bonjour à tous,
j'ai deux applications en C, la première contient une structure, et j'aimerai accéder à cette structure à partir de la deuxième application afin de pouvoir lire et écrire dans cette structure.
donc j'aimerai faire communiquer ces deux programmes en C.
J'ai vu qu'on peut utiliser la mémoire partagé pour le faire, mais je ne sais pas vraiment comment faire.
Si quelqu'un peut m'aider svp.
 
Merci d'avance.
 

Reply

Marsh Posté le 29-11-2011 à 16:56:02   

Reply

Marsh Posté le 29-11-2011 à 17:13:50    

C sur Windows, ou C sur Unix, ou autre.
 
Avec Windows, on peut envoyer un message, de type "User-defined message", à l'autre application et passer des données en paramètre. L'autre application peut capter ce message dans sa boucle de gestion des messages, et agir en conséquence. Il est aussi possible de mettre les données dans le presse-papier (clipboard).
 
Avec Unix, on peut utiliser la mémoire partagée. Voir http://en.wikipedia.org/wiki/Inter [...] munication .

Reply

Marsh Posté le 29-11-2011 à 20:32:04    

Tu as un large choix de moyen de communiquer entre différents processus : les mécanismes IPC ( file de message, shared memory ), les tubes , de simples fichiers, des sockets, des communications réseaux.  
 
Certains n'existent que sous Unix, d'autres sous windows également.
 
Après, il faut choisir le moyen le plus adapté à ce que tu souhaites faire.

Reply

Marsh Posté le 30-11-2011 à 09:30:08    

Bonjour, et merci pour vos réponses.
 
Actuellement mes deux applications communiquent via un fichier.
Application 1 modifie le fichier, Application 2 lie le fichier et va modifier dans la structure où sont stockés les données du fichier.
sauf que ce traitement prend du temps, d’où le choix d'aller directement modifier les valeurs dans la structure pour un traitement plus rapide.
Mes deux application sont sur Windows et en C.
Voila donc je ne sais ce qui est le plus adapté.  
 
Merci d'avance.
 

Reply

Marsh Posté le 30-11-2011 à 11:23:01    

Sous windows, tu peux utiliser les shared memory file : http://msdn.microsoft.com/en-us/library/dd997372.aspx
 
Attention cependant, c'est du code non portable, et l'exemple que je te donne nécessite .net framework.
 
Il me semble qu'il existe une version win32 au cas où tu ne puisses pas utiliser .net framework ( car c'est pas du C, c'est du C++ managé made in microsoft ).
 
Sinon, si tu veux une solution portable, une solution est de communiquer via une socket réseau, en mode connecté ou non. ( man socket/open/connect/accept/bind/send/recv/close/shutdown sous google ).

Reply

Marsh Posté le 30-11-2011 à 16:48:31    

Merci xilebo pour ta réponse,
 
Voila j'ai suivi ton conseil et j'ai regardé un peu les sockets.
j'ai fait deux applications pour tester le fonctionnement des sockets avant d'attaquer mon projet.
j'ai fait un programme serveur et un client.
Dans mon programme serveur j'ai crée une structure Personnage qui contient le nom, le prénom et l'age.
Ensuite j'ai déclaré une variable Personnage et j'ai rempli ses composants:
J'ai réussi à envoyer les valeurs de cette structure à mon programme client.
 
Ma question est comment je pourrai à partir de mon programme Client changer par exemple les valeurs age, nom et prénom.
 
Merci d'avance


Message édité par filoo85 le 02-12-2011 à 09:59:12
Reply

Marsh Posté le 01-12-2011 à 06:38:39    

Pareil mais dans l'autre sens (client->serveur)? :)

Reply

Marsh Posté le 06-12-2011 à 13:59:42    

Bonjour,
 
la communication entre mon code serveur et mon code client marche avec les socket, mais je n'arrive pas à envoyer les données à partir du client vers le serveur, j'ai essayé de mettre un send dans mon client mais ça ne marche pas.
donc je n'arrive pas à communiquer dans l'autre sens client -> serveur, si quelqu'un peut m'aider.
 
Voila mon code serveur :  

Code :
  1. /* Socket et contexte d'adressage du serveur */
  2.     SOCKADDR_IN sin;
  3.     SOCKET sock;
  4.     socklen_t recsize = sizeof(sin);
  5.    
  6.     /* Socket et contexte d'adressage du client */
  7.     SOCKADDR_IN csin;
  8.     SOCKET csock;
  9.     socklen_t crecsize = sizeof(csin);
  10.     char buffer[32] = "hello serveur";
  11.     int sock_err;
  12.    
  13.    
  14.     if(!erreur)
  15.     {
  16.         /* Création d'une socket */
  17.         sock = socket(AF_INET, SOCK_STREAM, 0);
  18.        
  19.         /* Si la socket est valide */
  20.        if(!erreur)
  21.     {
  22.         sock = socket(AF_INET, SOCK_STREAM, 0);
  23.         /* Si la socket est valide */
  24.         if(sock != INVALID_SOCKET)
  25.         {
  26.             printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
  27.             /* Configuration */
  28.             sin.sin_addr.s_addr    = htonl(INADDR_ANY);   /* Adresse IP automatique */
  29.             sin.sin_family         = AF_INET;             /* Protocole familial (IP) */
  30.             sin.sin_port           = htons(23);         /* Listage du port */
  31.             sock_err = bind(sock, (SOCKADDR*)&sin, sizeof(sin));
  32.             /* Si la socket fonctionne */
  33.             if(sock_err != SOCKET_ERROR)
  34.             {
  35.                 /* Démarrage du listage (mode server) */
  36.                 sock_err = listen(sock, 5);
  37.                 printf("Listage du port %d...\n", 23);
  38.                 /* Si la socket fonctionne */
  39.                 if(sock_err != SOCKET_ERROR)
  40.                 {
  41.                     /* Attente pendant laquelle le client se connecte */
  42.                     printf("Patientez pendant que le client se connecte sur le port %d...\n", 23);       
  43.                     csock = accept(sock, (SOCKADDR*)&csin, &recsize);
  44.                     printf("Un client se connecte avec la socket %d de %s:%d\n", csock, inet_ntoa(csin.sin_addr), htons(csin.sin_port));
  45.     sprintf(monPersonnage.nom, "Martin" );
  46.     sprintf(monPersonnage.prenom, "Dupont" );
  47.     monPersonnage.age = 25;
  48.                     sock_err = send(csock, &monPersonnage, sizeof(monPersonnage), 0);
  49.                     if(sock_err != SOCKET_ERROR)
  50.                         printf("Chaine envoyée : %s\n", buffer);
  51.                     else
  52.                         printf("Erreur de transmission\n" );
  53.                     /* Il ne faut pas oublier de fermer la connexion (fermée dans les deux sens) */
  54.                     shutdown(csock, 2);
  55.                 }
  56.             }
  57.             /* Fermeture de la socket */
  58.             printf("Fermeture de la socket...\n" );
  59.             closesocket(sock);
  60.             printf("Fermeture du serveur terminee\n" );
  61.         }


 et voila mon code Client:
 

Code :
  1. WSADATA WSAData;
  2.     int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
  3.     SOCKET sock;
  4.     SOCKADDR_IN sin;
  5. char buffer[32] = "";
  6.    if(!erreur)
  7.     {
  8.         /* Création de la socket */
  9.         sock = socket(AF_INET, SOCK_STREAM, 0);
  10.         /* Configuration de la connexion */
  11.         sin.sin_addr.s_addr = inet_addr("127.0.0.1" );
  12.         sin.sin_family = AF_INET;
  13.         sin.sin_port = htons(23);
  14.         /* Si l'on a réussi à se connecter */
  15.         if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
  16.         {
  17.             printf("Connection à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
  18.            
  19.             /* Si l'on reçoit des informations : on les affiche à l'écran */
  20.   if(recv(sock, &monPersonnage, sizeof(monPersonnage), 0) != SOCKET_ERROR){
  21.                 printf("Recu client : %d\n", monPersonnage.age);
  22.    printf("Recu client : %s\n", monPersonnage.nom);
  23.    printf("Recu client : %s\n", monPersonnage.prenom);
  24.         }
  25.  }
  26.         /* sinon, on affiche "Impossible de se connecter" */
  27.         else
  28.         {
  29.             printf("Impossible de se connecter\n" );
  30.         }
  31.         /* On ferme la socket */
  32.         closesocket(sock);
  33.         #if defined (WIN32)
  34.             WSACleanup();
  35.         #endif
  36.     }
  37.     /* On attend que l'utilisateur tape sur une touche, puis on ferme */
  38.     getchar();
  39.     return EXIT_SUCCESS;
  40. }


Message édité par filoo85 le 06-12-2011 à 14:04:18
Reply

Marsh Posté le 06-12-2011 à 15:10:48    

je ne sais pas si le recv est bloquant ou non par défaut, mais s'il ne l'est pas, et que les données n'ont pas encore été envoyées, c'est normal que tu ne les recoives pas.
 
Voir la fonction select pour écouter avec attente. ( si select retourne qu'il y a des datas, faire le recv à ce moment là ).
 
 
Attention aussi lors de l'envoi de données ( des entiers 32bits par exemple) sur le réseau si les machines n'ont pas la même endianess.

Reply

Marsh Posté le 06-12-2011 à 15:34:31    

Désolé, mais je n'ai pas compris ce qu'il faut faire, la j'ai posté le code qui permet de transmettre des données du code serveur au code client, et ça marche.
Ce que je ne sais pas faire et d'envoyer des données de mon code Client à mon code serveur.
Donc qu'est ce qu'il faut ajouter à mon code client pour qu'il puisse envoyer des données via les sockets au code serveur.

Reply

Marsh Posté le 06-12-2011 à 15:34:31   

Reply

Marsh Posté le 06-12-2011 à 15:49:32    

C'est le meme code mais dans l'autre sens. Ton client fait un send, et ton serveur un recv. Par contre, il faut veiller à être bien synchronisé pour que le recv du serveur soit bien fait après le send du client.

Reply

Marsh Posté le 06-12-2011 à 17:23:20    

Peux tu stp me montrer dans mon code ou est ce qu'il faut mettre le send dans le code client, car je suis un peu perdu.
Je l'ai mis avant la fermeture de la socket mais ça ne marche pas.et pareil pour le code serveur j'ai mis le recv avant la fermeture de la socket.
Merci d'avance.

Reply

Marsh Posté le 06-12-2011 à 17:29:19    

comme je t'ai dit plus haut, si ton recv retourne avant que le send soit fait, il va rien recevoir et quitter. Il faut donc que ton recv attende un temps suffisant ( par exemple une seconde ) avant de considérer qu'il ne recevra pas de données.
 
Tu fais ça avec un select de la façon suivante :
 

Code :
  1. timeval t;
  2. t.tv_sec = 1;
  3. t.tv_usec = 0; // 1000ms de timeout
  4. int valret;
  5. int lenret;
  6. fd_set ensemble;
  7. FD_ZERO(&ensemble);
  8. FD_SET(ma_socket,&ensemble);
  9. valret = select( ma_socket+1, &ensemble, 0, 0, &t);
  10. // tester les différents cas de valret
  11. // le cas qui dit qu'on a recu des données avant 1 seconde est le suivant :  
  12. if(FD_ISSET(ma_socket,&ensemble)!=0) // des données sont recues
  13. {
  14. lenret= recv(ma_socket,buffer,tailledubuffer,0);
  15. }


 
select va attendre jusqu'à 1 seconde pour voir si des données ont été reçues. Si avant 1 seconde c'est le cas, select retourne immédiatement avec une valeur de retour t'indiquant que des données sont reçues, il te suffit alors de faire un recv derrière pour les récupérer.
 
je te laisse l'adapter à ton code.


Message édité par xilebo le 06-12-2011 à 17:31:11
Reply

Marsh Posté le 06-12-2011 à 20:03:44    

Quelques remarques :

  • recv() pour les sockets TCP (SOCK_STREAM) est bloquant, le select() est inutile pour attendre les données. Pour rendre l'appel non-bloquant il faut passer par ioctlsocket() (Windows) ou fcntl() (le reste).
  • Les sockets sont bidirectionnelles, du peux appeler recv/send du client ou du serveur. À faire attention tout de même: si le client et le serveur appellent recv() alors qu'aucune donnée n'a été envoyée: bah tes processus vont attendre indéfiniements (là le select() peux être utile pour éviter ce genre de problème).
  • Tu écris des données binaire brute dans une socket. Je me doute que tu utilise ça sur la même machine, et le même compilateur pour le client et le serveur. Fait quand même gaffe aux problèmes d'endianess, padding et alignement des structures (classique, mais on oublie vite).

Reply

Sujets relatifs:

Leave a Replay

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