Client-serveur avec socket en C (client) vers PHP (serveur)

Client-serveur avec socket en C (client) vers PHP (serveur) - C - Programmation

Marsh Posté le 08-02-2006 à 14:54:39    

Slt à tous,
 
J'espère que je poste bien dans le bon forum, désolé si ce n'est pas le cas.
 
Je cherche à faire un client serveur avec des socket. Je voudrai avoir des clients en language C et un serveur en PHP. Je débute et ne sais pas trop comment m'y prendre. Je cherche pour le moment à faire un client-serveur très simple, juste réussir à communiquer pour comprendre comment cela fonctionne.
 
Quelqu'un pourrat'il m'aider.
 
Merci
Vilo


Message édité par Vilo5 le 08-02-2006 à 14:56:18
Reply

Marsh Posté le 08-02-2006 à 14:54:39   

Reply

Marsh Posté le 08-02-2006 à 15:00:12    

Reply

Marsh Posté le 08-02-2006 à 15:44:50    


 
Merci bien.
 
Je viens de regarder ce site, le client et le serveur son en C mais ca peut être un bon départ.
Il faut maintenant que je comprenne le code.
 
Une idée pour le serveur en PHP ? Et comment faire communiquer un client c avec un serveur php ?

Message cité 1 fois
Message édité par Vilo5 le 08-02-2006 à 15:46:46
Reply

Marsh Posté le 08-02-2006 à 21:27:23    

Vilo5 a écrit :

Merci bien.
 
Je viens de regarder ce site, le client et le serveur son en C mais ca peut être un bon départ.
Il faut maintenant que je comprenne le code.
 
Une idée pour le serveur en PHP ? Et comment faire communiquer un client c avec un serveur php ?


 
Un serveur php ? Je pense plutôt qu'il s'agit d'un serveur Apache. Mais regarde donc du coté des fonctions "socket()" dans la doc php... Et va voir aussi sur le forum hardware dans la rubrique php...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 13-02-2006 à 08:52:43    

Bon alors je suis en train de tester le client-serveur tcp télecharger sur http://pont.net/socket/, merci JagStang pour le lien.
 
Je voudrai avoir quelque précision pour comprendre comment il marche :
 
L'orsque je lance le serveur il me dit :

Citation :

../serveur: waiting for data on port TCP 1500


et le client :  

Citation :

usage: ./client <server> <data1> <data2> ... <dataN>


 
Je voudrai comprendre dans le client a quoi sert le test suivant :

Code :
  1. if(argc < 3) {
  2.     printf("usage: %s <server> <data1> <data2> ... <dataN>\n",argv[0]);
  3.     exit(1);
  4.   }


 
Que signifie les variables "int argc, char *argv[]" ?
 
Merci d'avance


Message édité par Vilo5 le 13-02-2006 à 09:09:00
Reply

Marsh Posté le 13-02-2006 à 12:08:41    

Ce sont les arguments que tu passent au programme. argc et le nombre, argv[] sont les parametres. En fait argc vaut toujours au moins 1, et argv[0] c'est le nom de ton programme.  
dans ton cas, il faut passer un argument l'ip et le port du server je pense, donc au moins 3 arguments :
client.exe 192.168.1.110 1500  , pour dire a ton client que le server est sur l'adresse 192.... et sur le port 1500. argv[0] est le nom de l'exe client et ensuite argv[1] = ip server argv[2] le port...
Mais document toi un peu sur le main() d'un programme C ..  

Reply

Marsh Posté le 13-02-2006 à 14:13:48    

francky06l a écrit :

Ce sont les arguments que tu passent au programme. argc et le nombre, argv[] sont les parametres. En fait argc vaut toujours au moins 1, et argv[0] c'est le nom de ton programme.  
dans ton cas, il faut passer un argument l'ip et le port du server je pense, donc au moins 3 arguments :
client.exe 192.168.1.110 1500  , pour dire a ton client que le server est sur l'adresse 192.... et sur le port 1500. argv[0] est le nom de l'exe client et ensuite argv[1] = ip server argv[2] le port...
Mais document toi un peu sur le main() d'un programme C ..


 
Ok merci bien, je vois.
 
Pourrait tu m'aider a configurer mon client pour l'adapter a ce que je veut faire.
Pour le moment je souhaite juste créer un client tcp qui se connecte à un serveur "IP:127.0.0.1 sur le port 80" et lui envoie 3 variable x, y, z qui seront pour le moment entrées en dure dans le programme (x=1, y=2, z=3).
 
J'utilise comme base de départ le programme client tcp trouvé a cette adresse : http://pont.net/socket/
Et le serveur est déjà réalisé en php avec la librairie nusoap.
 
J'ai donc juste besoin d'un coup d emain pour réaliser mon client qui comme expliquer ci dessus se contente d'envoyer 3 variables x, y et z au serveur.
 
merci

Reply

Marsh Posté le 13-02-2006 à 18:19:09    

Salut, j'te renvoie à mon sujet tout fraichement posté :
http://forum.hardware.fr/hardwaref [...] 4747-1.htm
 
Ce dernier prend ton problème à l'envers, mon serveur est en C et mon client en php. Le code marche sauf quand on envoie rien pendant une durée trop longue (c'était le sujet de mon problème) et ça peut toujours t'aider.
Ciao

Reply

Marsh Posté le 13-02-2006 à 23:04:51    

krocky a écrit :

Salut, j'te renvoie à mon sujet tout fraichement posté :
http://forum.hardware.fr/hardwaref [...] 4747-1.htm
 
Ce dernier prend ton problème à l'envers, mon serveur est en C et mon client en php. Le code marche sauf quand on envoie rien pendant une durée trop longue (c'était le sujet de mon problème) et ça peut toujours t'aider.
Ciao


 
Oui j'avais vu ton sujet, mais bon comme tu le dit le pb est à l'envers, de plus ton code en C est pour windows alors que moi mon code en C (le client dans mon cas) sera pour linux. Ca ne m'aide donc pas bc mais merci tout de même. De plus je ne comprend pas vraiment ta logique de faire un client en php et un serveur en C, ca me parait illogique le php est normalement du côté client.
 
Enfin bref, moi j'essaye de comprendre comment utiliser la librairie gsoap ou autre sous linux.

Reply

Marsh Posté le 14-02-2006 à 07:01:25    

Pour envoyer x, y, z, ton programme doit prendre 3 arguments supplementaire. Donc argc >= 6, et x, y, z se trouve dans argv[3], argv[4], argv[5]. Je ne sais pas comment est ton serveur, il y a plusieurs facons de transporter ces donnees, en binaire ou en "string". Si c'est en binaire il faut connaitre le "type" (int, int64, short) et transformer argv[3] en utilsant int x = atoi(argv[3]).... Ensuite il faut envoyer tout ca au server en utilisant snd(s, &x, sizeof(int)) ... Encore une fois cela depend de ce qu'attend ton serveur (surtout le format des donnees).

Reply

Marsh Posté le 14-02-2006 à 07:01:25   

Reply

Marsh Posté le 14-02-2006 à 10:43:08    

francky06l a écrit :

Pour envoyer x, y, z, ton programme doit prendre 3 arguments supplementaire. Donc argc >= 6, et x, y, z se trouve dans argv[3], argv[4], argv[5]. Je ne sais pas comment est ton serveur, il y a plusieurs facons de transporter ces donnees, en binaire ou en "string". Si c'est en binaire il faut connaitre le "type" (int, int64, short) et transformer argv[3] en utilsant int x = atoi(argv[3]).... Ensuite il faut envoyer tout ca au server en utilisant snd(s, &x, sizeof(int)) ... Encore une fois cela depend de ce qu'attend ton serveur (surtout le format des donnees).


 
Ok d'accord donc mon test sur argc devra être : argc<6
 
Je vous communique le code de mon serveur en PHP (sous windows) qui fonctionne pour le moment avec un client en PHP sous windows mais que je souhaite donc remplacer par un client en C sous Linux :
 

Code :
  1. <?php
  2. include('../lib/nusoap.php');
  3. $serveur = new soap_server;
  4. $serveur->debug_flag=false;
  5. $serveur->register('CA');
  6. // FONCTION DE CONTROLE D'ACCES
  7. function CA($num_site, $num_term, $num_carte)
  8. {
  9.  // CONNEXION AU SERVEUR SQL
  10.  require("connect_bdd.php" );
  11.  // SELECTION D'UNE BASE
  12.  $db_selected = mysql_select_db('ca', $link);
  13.  if (!$db_selected)
  14.  {
  15.     die('Impossible de sélectionner la base de données : ' . mysql_error());
  16.  }
  17.  // REQUETE PERMETTANT DE COMPTER LE NOMBRE D'ENTREE CORRESPONDANT A LA COMBINAISON
  18.  $requete = mysql_query("SELECT COUNT(num_carte) AS nb FROM autorisation WHERE
  19.             num_site='$num_site' AND num_term='$num_term' AND num_carte='$num_carte'" );
  20.                
  21.  if (!$requete)
  22.  {
  23.  die('Requête invalide : ' . mysql_error());
  24.  }
  25.  // RECUPERATION DU RESULTAT DE LA REQUETE
  26.  $resultat = mysql_result($requete,0);
  27.  // DEDUCTION DU DROIT D'ACCES EN FONCTION DU RESULTAT  
  28.  if ($resultat==0)
  29.  {
  30.     $droit=0;
  31.  }
  32.  else
  33.  {
  34.     $droit=1;
  35.  }
  36.  // RETOURNE LE DROIT
  37.  return "La <b>carte $num_carte</b> tente de badger sur le <b> terminal $num_term</b> du
  38.             <b>site $num_site</b>. <br><br> <b>Son droit d'accès est $droit</b>.";
  39.  // FERME LE SERVEUR
  40.  mysql_close($link);
  41. }
  42. $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA)? $HTTP_RAW_POST_DATA : '';
  43. // ENVOI LE RETOUR DE LA FONCTION AU CLIENT
  44. $serveur->service($HTTP_RAW_POST_DATA);
  45. ?>


 
Comme vous pouvez le voir mon serveur éxécute une fonction  de contôle d'accès en interrogeant une base de données en fonction des 3 variables envoyés par le client (num-site, num_term et num_carte qui sont en faite les 3 variables x, y et z dont je vous parler avant). La fonction retourne donc ensuite un droit d'accès qui est 0 ou 1 et renvoie se résultat au client.
 
Voilà il me faut donc un client linux en c qui envoie ces 3 variables au serveur puis récupère le résultat de la fonction "CA" du serveur a savoir le droit d'accès 0 ou 1.

Reply

Marsh Posté le 14-02-2006 à 10:57:07    

Je suis pas un pro en PHP, mais la vue du code poste ne me donne pas d'indications quant au format des datas. La reception semble faite dans function CA, mais ce n'est pas explicite du point de vue socket...

Reply

Marsh Posté le 14-02-2006 à 11:10:02    

Et bien les 3 variables seront tout simplement des entiers.

Reply

Marsh Posté le 14-02-2006 à 11:38:00    

Bon je vais essayer de voir la chose dans un autre sens, immaginons que mes structure sont déjà déclarées.
 
Comment dois-je écrire dans mon serveur la fonction send qui enverra mes 3 variables (entiers) au serveur ?
Comment dois-je écrire dans mon client la fonction receive qui recevra la réponse à savoir le droit d'accès (encore une fois une variable de type entiers ou encore booléen)?


Message édité par Vilo5 le 14-02-2006 à 11:38:32
Reply

Marsh Posté le 14-02-2006 à 11:47:21    

Dans ce cas, tu peux ecrire ce genre de chose :
 
   int i;
   int tab[3];
   socket s;
   int      rc;
 
   for(i=0; i < 3; i++)
       tab[i] = atoi(argv[i+3]);
 
   // tu dois avoir cette partie deja dans le client exemple
   connect(s, .. .. ..);
 
   // envoi des 3 entiers
 
   rc = send(s, tab, sizeof(int)*3);
 
   if(rc != -1)  // test error  
     rc = recv(s, tab, sizeof(int));  // ici on suppose que ta reponse bool sera un int (0 ou 1), stockee dans tab[0]
 
   closesocket(s);
 
   if(rc != -1)
     // process ta reponse (0 ou 1)
 
   
 
voila en gros l'approche, mais considere que dans ce shema on prend des int (attention ils ne sont pas endianess). Si ton serveur PHP attend autre chose que des int ca marchera pas..

Reply

Marsh Posté le 14-02-2006 à 15:18:48    

Bon voilà j'ai écrit un code mais je ne suis pas du tout sure de mon coup, je rapelle que je débute dans le domaine alors soyez indulgent  :pt1cable:  
 
voilà le code :

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <string.h>
  5. #include <netdb.h>
  6. #include <sys/types.h>
  7. #include <netinet/in.h>
  8. #include <sys/socket.h>
  9. #define serveur_port 80
  10. #define serveur_ip "192.168.0.29"
  11. int main(int argc, char *argv[])
  12.     {
  13.     int i;
  14.     int tab[3];
  15.     int sock;
  16.     int rc;
  17.     struct sockaddr_in mon_adresse, client_adresse;
  18.     argv[0]= "client.h";    // nom du client
  19.     argv[1]= serveur_ip;    // ip du serveur
  20.     argv[2]= serveur_port;  // port du serveur
  21.     argv[3]= 1;             // num_site
  22.     argv[4]= 1;             // num_term
  23.     argv[5]= 1;             // num_carte
  24.     for(i=0;i<3;i++)
  25.     {
  26.       tab[i] = atoi(argv[i+3]);
  27.     }
  28.     mon_adresse.sin_family = AF_INET;
  29.     mon_adresse.sin_port = htons(serveur_port);
  30.     mon_adresse.sin_addr.s_addr = htonl(INADDR_ANY);
  31.     bzero(&mon_adresse, sizeof(mon_adresse));
  32.     // création du socket
  33.     sock = socket(AF_INET, SOCK_STREAM, 0);
  34.     if (sock<0)
  35.     {
  36.         pintf("Ne peut pas ouvrir le socket " );
  37.         exit(1);
  38.     }
  39.     // on attache le socket à la structure déclaré précèdement
  40.     rc = bind(sock, (struct sockaddr *)&mon_adresse, sizeof(mon_adresse));
  41.     if (sd<0)
  42.     {
  43.         pintf("%s: Ne peut pas effectuer le bind sur le port TCP %u\n", argv[0], PORT);
  44.         exit(1);
  45.     }
  46.     // envoi des 3 entiers
  47.     sd = send(sock, tab, sizeof(int)*3);
  48.     if(rc != -1) // test error
  49.     {
  50.         while(1)
  51.         {
  52.         rc = recv(sock, tab, sizeof(int));
  53.         }
  54.     }
  55.     close(sock);  // fermeture du socket
  56.     // process de ma reponse (suivant si j'ai 0 ou 1)
  57.     // pour le moment je fais un process de test bidon pour commencer
  58.     if(rc != -1)
  59.     {
  60.         if tab[0]=0
  61.         {
  62.             printf("Le droit est 0" )
  63.         }
  64.         if tab[0]=1
  65.         {
  66.             printf("Le droit est 1" )
  67.         }
  68.     }
  69. }


 
Est-ce que ca parait juste par rapport a ce que je souhaite faire (voir message précédent).

Reply

Marsh Posté le 14-02-2006 à 15:27:41    

euh non, pas besoin de bind normalement. SI c'est bien le cote client que tu programme, il faut un connect() pas un bind ..Par contre si tu faus pas de connect du tout, ca se connectera pas..
Enfin on peut faire un bind AVANT un connect, mais c'est pas conseille .. Le connect bindera automatiquement sur un couple Ip/port libre.
 
il faut retirer le bzero the mon_adress et le mettre avant l'adresse serveur, sinon tu mets l'adress serveur mais tu l'ecrases apres..
 
A la place du bind :
connect(sock, &mon_adress, sizeof(mon_adress));
 
le send, il manque un autre parametre apres la sizeof(int), ajoute ,0
pareil pour le recv
 
good luck

Reply

Marsh Posté le 14-02-2006 à 15:32:36    

Ok merci, c'est sympa, désolé pour le côté newby.
 
je vais changer ca et je repost juste après.

Reply

Marsh Posté le 14-02-2006 à 16:13:12    

voilà ce que ca donne si j'ai bien compris ce que tu ma dis :
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <string.h>
  5. #include <netdb.h>
  6. #include <sys/types.h>
  7. #include <netinet/in.h>
  8. #include <sys/socket.h>
  9. #define serveur_port 80
  10. #define serveur_ip "192.168.0.29"
  11. int main(int argc, char *argv[])
  12. {
  13.     int i;
  14.     int tab[3];
  15.     int sock;
  16.     int rc;
  17.     struct sockaddr_in mon_adresse;
  18.     argv[0]= "client.h";    // nom du client
  19.     argv[1]= serveur_ip;    // ip du serveur
  20.     argv[2]= serveur_port;  // port du serveur
  21.     argv[3]= 1;             // num_site
  22.     argv[4]= 1;             // num_term
  23.     argv[5]= 1;             // num_carte
  24.     for(i=0;i<3;i++)
  25.     {
  26.       tab[i] = atoi(argv[i+3]);
  27.     }
  28.     bzero(&mon_adresse, sizeof(mon_adresse));
  29.     mon_adresse.sin_family = AF_INET;
  30.     mon_adresse.sin_port = htons(serveur_port);
  31.     mon_adresse.sin_addr.s_addr = htonl(INADDR_ANY);
  32.     // création du socket
  33.     sock = socket(AF_INET, SOCK_STREAM, 0);
  34.     if (sock<0)
  35.     {
  36.         pintf("Ne peut pas ouvrir le socket " );
  37.         exit(1);
  38.     }
  39.     connect(sock, &mon_adress, sizeof(mon_adress));
  40.     // envoi des 3 entiers
  41.     rc = send(sock, tab, sizeof(int)*3, 0);
  42.     if(rc != -1) // test error
  43.     {
  44.         while(1)
  45.         {
  46.         rc = recv(sock, tab, sizeof(int));
  47.         }
  48.     }
  49.     close(sock);  // fermeture du socket
  50.     // process de ma reponse (suivant si j'ai 0 ou 1)
  51.     // pour le moment je fais un process de test bidon pour commencer
  52.     if(rc != -1)
  53.     {
  54.         if tab[0]=0
  55.         {
  56.             printf("Le droit est 0" )
  57.         }
  58.         if tab[0]=1
  59.         {
  60.             printf("Le droit est 1" )
  61.         }
  62.     }
  63. }

Reply

Marsh Posté le 11-03-2006 à 12:00:54    

As-tu essayé ton code ?
Car la directive suivante est utilisée dans le cas d'un serveur :
 

Code :
  1. mon_adresse.sin_addr.s_addr = htonl(INADDR_ANY);


 
tu indique n'importe quelle adresse, alors que justement tu dois te connecter sur une adresse précise.
 

Code :
  1. mon_adresse.sin_addr.s_addr = inet_addr(serveur_ip);


 
serait plus approprié !
 
++

Message cité 1 fois
Message édité par thechief le 11-03-2006 à 12:03:59
Reply

Marsh Posté le 11-03-2006 à 19:28:43    

Vilo5 a écrit :

voilà ce que ca donne si j'ai bien compris ce que tu ma dis :


Regarde mes commentaires dans ton source...
 

Code :
  1. argv[0]= "client.h";    // nom du client
  2.     // Le nom du client ce serait plutôt le nom de l'exécutable et non le nom du header...
  3.     argv[1]= serveur_ip;    // ip du serveur
  4.     argv[2]= serveur_port;  // port du serveur
  5.     argv[3]= 1;             // num_site
  6.     argv[4]= 1;             // num_term
  7.     argv[5]= 1;             // num_carte
  8.     for(i=0;i<3;i++)
  9.     {
  10.       tab[i] = atoi(argv[i+3]);
  11.     }
  12.     // Peut être que faire démarrer "i" à 3 éviterait ce "[i + 3]"
  13.     // De plus, à quoi sert de remplir argv[0...1...2] si tu ne les utilises pas ???
  14.     bzero(&mon_adresse, sizeof(mon_adresse));
  15.     // bzero c'est pas standard. Il est préférable d'utiliser "memset"


 

thechief a écrit :

tu indique n'importe quelle adresse, alors que justement tu dois te connecter sur une adresse précise.


En fait, INADDR_ANY ne signifie pas "n'importe quelle adresse" mais simplement "adresse 0.0.0.0". C'est une macro qui vaut "0", qu'on utilise pour le serveur et qui signifie conventionnellement "pas besoin d'indiquer d'adresse car je suis le serveur"


Message édité par Sve@r le 11-03-2006 à 19:30:03

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 11-03-2006 à 20:59:44    

C'est à peu près ce que je voulais dire, merci des précisions ;)

Reply

Marsh Posté le 11-03-2006 à 21:07:59    

thechief a écrit :

C'est à peu près ce que je voulais dire, merci des précisions ;)


Avec plaisir... :jap:  


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 12-03-2006 à 10:56:58    

J'ai un problème de socket aussi.
Désolé de squatter vilo5 ...
 
Voici ma portion de code
 

Code :
  1. while(socket_c != INVALID_SOCKET)
  2.       {
  3.        
  4.       if((recevoir =  recv(socket_c, buffer_recv,512,0)) != SOCKET_ERROR) // Reception des données
  5.            {
  6.                   printf("%s\n", buffer_recv);
  7.            }
  8.       else
  9.            {
  10.            printf("Erreur : reception des donnees impossible\n" );
  11.            }
  12.          
  13.       fgets(buffer_send, sizeof(buffer_send), stdin);
  14.      
  15.       if ((envoyer = send(socket_c, buffer_send, strlen(buffer_send), 0)) != strlen(buffer_send)){ // Envoyer les données
  16.          printf("Erreur : Envois des donnees impossible\n" );
  17.          return 0;
  18.          }
  19.      
  20.       }


 
Mon client se connecte correctement sur le serveur...
Mais juste après il m'affiche les deux erreurs possibles et se termine.
Alors que je n'ai rien envoyé coté serveur.
Ou est l'erreur ?
 
merci

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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