[C] et les sockets ...

Discutez d'informatique ici !
Kwak
Membre Naturel
Messages: 16
Enregistré le: 26 Nov 2006, 17:49

[C] et les sockets ...

par Kwak » 01 Déc 2006, 20:24

Bonsoir à tous !

J'aimerais vous demander comment pouvoir poser une question du serveur au client.

J'ai très bien comprit les send() recv() etc .. (j'ai déjà codé) mais je ne vois pas comment faire pour que le client rentre une saisie et me la renvoie.

Merci d'avance!



anima
Membre Transcendant
Messages: 3762
Enregistré le: 15 Sep 2006, 11:00

par anima » 01 Déc 2006, 21:06

Kwak a écrit:Bonsoir à tous !

J'aimerais vous demander comment pouvoir poser une question du serveur au client.

J'ai très bien comprit les send() recv() etc .. (j'ai déjà codé) mais je ne vois pas comment faire pour que le client rentre une saisie et me la renvoie.

Merci d'avance!


En C, c'est tordu: boucle infinie :zen:

Kwak
Membre Naturel
Messages: 16
Enregistré le: 26 Nov 2006, 17:49

par Kwak » 02 Déc 2006, 08:57

Comment ça ?
en fait je ne vois pas trop la syntaxe que je devrais avoir pour faire ça.
Ce qui se passe, c'est que je pense qu'il faut que je récupère la saisie via fgets. mais comment envoyer une commande pareille ? C'est ça que je ne comprends pas :hein:

Merci bien ;)

Dominique Lefebvre
Membre Légendaire
Messages: 8005
Enregistré le: 03 Déc 2005, 12:00

par Dominique Lefebvre » 02 Déc 2006, 09:03

Kwak a écrit:Comment ça ?
en fait je ne vois pas trop la syntaxe que je devrais avoir pour faire ça.
Ce qui se passe, c'est que je pense qu'il faut que je récupère la saisie via fgets. mais comment envoyer une commande pareille ? C'est ça que je ne comprends pas :hein:

Merci bien ;)


Bonjour,

Si ça peut t'aider voilà un bout de code que j'ai écris il y aqq années pour faire un prog client serveur sur sockets:

void main(int argc, char *argv[])
{
struct sockaddr_in ServAddr;
struct sockaddr_in ClntAddr;
int BytesRcvd;
int FinBoucleProg;
int ClntLen;
char sCommand[RCVBUFSIZE];
unsigned short uiPort;
char servIP[20];
char suiPort[10];
int CodeErreur;
WSADATA wsaData;
HANDLE hThread;
DWORD dwThreadId;


//** Initialisation des variables depuis la base de registre
CodeErreur = LectureRegKey("Software\\PiloteDialogic","IPRouter",servIP);
CodeErreur = LectureRegKey("Software\\PiloteDialogic","Port",suiPort);
uiPort = atoi(suiPort);

//** Initialisation de la Dll Winsock 2.0
if (WSAStartup(MAKEWORD(2,0),&wsaData) != 0)
{
fprintf(stderr,"Erreur d'initialisation WSAStartUp");
exit(1);
}

//** Initialisation de la carte Dialogic et ouverture de toutes les voies de la carte
CodeErreur = InitDialogic ();
if (CodeErreur != 0)
{
DebugTrace("Erreur initialisation Dialogic");
printf("Erreur initialisation Dialogic \n");
}

//** Ouverture de la socket Serveur
if ((sock_serv = socket(AF_INET, SOCK_STREAM, 0)) < 0)
WinsockException("Erreur sur ouverture socket");

//** Nommage de la socket Serveur
memset(&ServAddr,0,sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = inet_addr(servIP);
ServAddr.sin_port = htons(uiPort);


//** Bind de la socket Serveur sur l'adresse locale
if (bind(sock_serv,(struct sockaddr *) &ServAddr, sizeof(ServAddr)) < 0)
WinsockException("Erreur sur bind socket");

//** Attente de connexion entrante sur la socket Serveur
if (listen(sock_serv,MAXPENDING) < 0)
WinsockException("Erreur sur listen socket");

printf("Connexion sur %s port %d\n",inet_ntoa(ServAddr.sin_addr),ServAddr.sin_port);

//** le programme se met en attente de la première connexion du multiplexeur ou de l'automate
//** lorsque la connexion est établie, il créé une socket de dialogue avec l'agent client
ClntLen = sizeof(ClntAddr);
if ((sock_client = accept(sock_serv,(struct sockaddr *) &ClntAddr,&ClntLen)) < 0)
WinsockException("Erreur sur accept");

//** puis on boucle sur cette socket jusqu'à réception de FIN
FinBoucleProg = VRAI;
while (FinBoucleProg)
{

//** Lecture des données reçues sur la socket
if ((BytesRcvd = recv(sock_client,sCommand,RCVBUFSIZE,0)) < 0)
WinsockException("Erreur de lecture");

//** Mise en forme de l'ordre reçu
sCommand[BytesRcvd] = '\0';
printf("recu : %s\n",sCommand);

//** Création d'un thread pour traiter la commande reçue
hThread = CreateThread(NULL, 0, DialogicProceed, sCommand, 0, &dwThreadId);
CloseHandle(hThread);

} // fin boucle principale du programme


//** Fermeture de la socket et fin du programme
closesocket(sock_client);
closesocket(sock_serv);
WSACleanup;
DebugTrace("Fin du programme PiloteDialogic");

exit(0);
}

Kwak
Membre Naturel
Messages: 16
Enregistré le: 26 Nov 2006, 17:49

par Kwak » 02 Déc 2006, 19:36

wow merci !

anima
Membre Transcendant
Messages: 3762
Enregistré le: 15 Sep 2006, 11:00

par anima » 02 Déc 2006, 21:55

Kwak a écrit:wow merci !


Fais gaffe avec le code de Domi. Il utilise la version windows de winsock, et donc ca ne pourra pas être compilé sous linux. Mais autrement, ca marche impec :zen:

Dominique Lefebvre
Membre Légendaire
Messages: 8005
Enregistré le: 03 Déc 2005, 12:00

par Dominique Lefebvre » 03 Déc 2006, 11:30

anima a écrit:Fais gaffe avec le code de Domi. Il utilise la version windows de winsock, et donc ca ne pourra pas être compilé sous linux. Mais autrement, ca marche impec :zen:


Bonjour,
Oui, c'est une version windows. Mais il y très peu de différence entre les versions Unix et Windows de Socket. Elles portent sur les formats des structure d'adresses IN et dans l'usage des routines WSA qi sont propres à Windows..

Si tu veux, je dois avoir dans ma doc. les différences précises... Le temps de chercher dans mon fatras!

Heu... je confirme que ce machin fonctionne tous les jours, 24 heures par jour depuis 2004!

Dominique Lefebvre
Membre Légendaire
Messages: 8005
Enregistré le: 03 Déc 2005, 12:00

par Dominique Lefebvre » 03 Déc 2006, 11:39

Voilà, il suffisait de patienter...
Voici un exemple de client unix (développé pour SCO et Mandrake 8.0) qui se connecte sur un serveur TCP-IP qui tourne sous W2000 (qui supporte le code que j'ai donné ci-dessus). Cela te donne une idée des différences:

// **************************************************************************************
// **************************************************************************************
// ***
// *** Source : clientSCO.c
// *** OS : Unix (testé sous Linux Mandrake 8.0)
// *** Dominique Lefebvre
// ***
// *** Version 1.0 du 14 septembre 2002
// ***
// ***
// ***
// **************************************************************************************
// **************************************************************************************


//** librairies standard
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define FAUX 0
#define VRAI !FAUX

//** constantes socket
#define MAXPENDING 5

//** constantes du tube FIFO
#define NOM_FIFO "/tmp/fifo_sco"


// ***************************************************************************************
// ***************************************************************************************
// Programme principal
//
// Ce programme traite l'ensemble des ordres transmis par l'automate Dialogic concernant
// la voie passée en paramètre lors du lancement du process.
//
// ***************************************************************************************
int main(int argc, char *argv[])
{
struct sockaddr_in ServAddr;
int hfifo; // Handle du fifo
int sock_serv; // Socket Serveur
int BytesRcvd;
int FinBoucleProg;
char sCommand[PIPE_BUF];
unsigned short uiPort;
char* servIP;
char* suiPort;
int CodeErreur;
int mode_open;

//** on récupère les paramètres de connexion au serveur W2000
//** Argv[1] = adresse IP du serveur
//** Argv[2] = port de connexion
if (argc == 3)
{
servIP = (char *)malloc(20);
suiPort = (char *)malloc(10);

servIP = argv[1];
suiPort = argv[2];
uiPort = atoi(suiPort);
}
else
{
fprintf(stderr,"clientsco - Le nombre de parametres est incorrect \n");
exit(EXIT_FAILURE);
}

printf("Lancement de clientsco - @IP %s Port %s \n\n",servIP,suiPort);


//** Création du tube FIFO s'il n'existe pas
if (access(NOM_FIFO,F_OK) == -1)
{
CodeErreur = mkfifo(NOM_FIFO,0777);
if (CodeErreur != 0)
{
fprintf(stderr,"clientsco - impossible de creer le FIFO %s\n",NOM_FIFO);
exit(EXIT_FAILURE);
}
}

//** Ouverture du FIFO en mode Write Only mode bloquant.
//** ATTENTION : le programme se positionne en attente tant que le programme Serveur SCO n'a pas ouvert le FIFO en lecture
mode_open = O_WRONLY;
printf("clientsco ouvre le FIFO %s en mode WRITE_ONLY bloquant et attend l'ouverture du FIFO en lecture par le serveur SCO \n",NOM_FIFO);
hfifo = open(NOM_FIFO, mode_open);
if (hfifo == -1)
{
fprintf(stderr,"clientsco - erreur d'ouverture du FIFO %s\n",NOM_FIFO);
exit(EXIT_FAILURE);
}
printf("clientsco est connecté au serveur SCO \n");

//** Ouverture de la socket Serveur
if ((sock_serv = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr,"clientsco - erreur sur ouverture du socket \n");
exit(EXIT_FAILURE);
}

//** Nommage de la socket Serveur
memset(&ServAddr,0,sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = inet_addr(servIP);
ServAddr.sin_port = htons(uiPort);
printf("Connexion sur %s:%d\n",inet_ntoa(ServAddr.sin_addr),ServAddr.sin_port);

//** On se connecte sur le serveur
if (connect(sock_serv,(struct sockaddr *) &ServAddr, sizeof(ServAddr)) < 0)
{
fprintf(stderr,"clientsco - erreur a la connexion du socket \n");
exit(EXIT_FAILURE);
}

//** puis on boucle sur cette socket jusqu'à réception de FIN
FinBoucleProg = VRAI;
while (FinBoucleProg)
{
//** Lecture des données reçues sur la socket
if ((BytesRcvd = recv(sock_serv,sCommand,PIPE_BUF,0)) < 0)
{
fprintf(stderr,"clientsco - erreur de lecture sur le socket \n");
break;
}

if (BytesRcvd > 0)
{
sCommand[BytesRcvd] = '\0';
//** Detection de l'ordre de fin de programme

if (strstr(sCommand,"fin transmission") != NULL)
{
FinBoucleProg = FAUX;
printf("Ordre d'arret de clientsco \n");
}
else
{
//** Ecriture du buffer reçu dans le fifo
CodeErreur = write(hfifo, sCommand, PIPE_BUF);
if (CodeErreur == -1)
{
fprintf(stderr,"Erreur d'ecriture sur le fifo %s \n", NOM_FIFO);
exit(EXIT_FAILURE);
}
}
}

} // fin boucle principale du programme


//** Fermeture de la socket , du fifo et fin du programme
close(hfifo);
close(sock_serv);
printf("Arret de clientsco \n");
exit(0);
}


J'ai été pessimiste, cela date déjà de 2002! Le temps passe vite...

anima
Membre Transcendant
Messages: 3762
Enregistré le: 15 Sep 2006, 11:00

par anima » 03 Déc 2006, 11:48

Dominique Lefebvre a écrit:Voilà, il suffisait de patienter...
Voici un exemple de client unix (développé pour SCO et Mandrake 8.0) qui se connecte sur un serveur TCP-IP qui tourne sous W2000 (qui supporte le code que j'ai donné ci-dessus). Cela te donne une idée des différences:

// **************************************************************************************
// **************************************************************************************
// ***
// *** Source : clientSCO.c
// *** OS : Unix (testé sous Linux Mandrake 8.0)
// *** Dominique Lefebvre
// ***
// *** Version 1.0 du 14 septembre 2002
// ***
// ***
// ***
// **************************************************************************************
// **************************************************************************************


//** librairies standard
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define FAUX 0
#define VRAI !FAUX

//** constantes socket
#define MAXPENDING 5

//** constantes du tube FIFO
#define NOM_FIFO "/tmp/fifo_sco"


// ***************************************************************************************
// ***************************************************************************************
// Programme principal
//
// Ce programme traite l'ensemble des ordres transmis par l'automate Dialogic concernant
// la voie passée en paramètre lors du lancement du process.
//
// ***************************************************************************************
int main(int argc, char *argv[])
{
struct sockaddr_in ServAddr;
int hfifo; // Handle du fifo
int sock_serv; // Socket Serveur
int BytesRcvd;
int FinBoucleProg;
char sCommand[PIPE_BUF];
unsigned short uiPort;
char* servIP;
char* suiPort;
int CodeErreur;
int mode_open;

//** on récupère les paramètres de connexion au serveur W2000
//** Argv[1] = adresse IP du serveur
//** Argv[2] = port de connexion
if (argc == 3)
{
servIP = (char *)malloc(20);
suiPort = (char *)malloc(10);

servIP = argv[1];
suiPort = argv[2];
uiPort = atoi(suiPort);
}
else
{
fprintf(stderr,"clientsco - Le nombre de parametres est incorrect \n");
exit(EXIT_FAILURE);
}

printf("Lancement de clientsco - @IP %s Port %s \n\n",servIP,suiPort);


//** Création du tube FIFO s'il n'existe pas
if (access(NOM_FIFO,F_OK) == -1)
{
CodeErreur = mkfifo(NOM_FIFO,0777);
if (CodeErreur != 0)
{
fprintf(stderr,"clientsco - impossible de creer le FIFO %s\n",NOM_FIFO);
exit(EXIT_FAILURE);
}
}

//** Ouverture du FIFO en mode Write Only mode bloquant.
//** ATTENTION : le programme se positionne en attente tant que le programme Serveur SCO n'a pas ouvert le FIFO en lecture
mode_open = O_WRONLY;
printf("clientsco ouvre le FIFO %s en mode WRITE_ONLY bloquant et attend l'ouverture du FIFO en lecture par le serveur SCO \n",NOM_FIFO);
hfifo = open(NOM_FIFO, mode_open);
if (hfifo == -1)
{
fprintf(stderr,"clientsco - erreur d'ouverture du FIFO %s\n",NOM_FIFO);
exit(EXIT_FAILURE);
}
printf("clientsco est connecté au serveur SCO \n");

//** Ouverture de la socket Serveur
if ((sock_serv = socket(AF_INET, SOCK_STREAM, 0)) 0)
{
sCommand[BytesRcvd] = '\0';
//** Detection de l'ordre de fin de programme

if (strstr(sCommand,"fin transmission") != NULL)
{
FinBoucleProg = FAUX;
printf("Ordre d'arret de clientsco \n");
}
else
{
//** Ecriture du buffer reçu dans le fifo
CodeErreur = write(hfifo, sCommand, PIPE_BUF);
if (CodeErreur == -1)
{
fprintf(stderr,"Erreur d'ecriture sur le fifo %s \n", NOM_FIFO);
exit(EXIT_FAILURE);
}
}
}

} // fin boucle principale du programme


//** Fermeture de la socket , du fifo et fin du programme
close(hfifo);
close(sock_serv);
printf("Arret de clientsco \n");
exit(0);
}


J'ai été pessimiste, cela date déjà de 2002! Le temps passe vite...


Trop vite à mon goût. Cela fera bientôt 7 ans que je programme :hein:

Dominique Lefebvre
Membre Légendaire
Messages: 8005
Enregistré le: 03 Déc 2005, 12:00

par Dominique Lefebvre » 03 Déc 2006, 11:54

anima a écrit:Trop vite à mon goût. Cela fera bientôt 7 ans que je programme :hein:


Et moi, je te dis pas! J'ai touché mon premier ordinateur (un IBM 370) à l'Ecole en 1977...
Ensuite les bijoux de calcul: HP1000 et VAX 1180

anima
Membre Transcendant
Messages: 3762
Enregistré le: 15 Sep 2006, 11:00

par anima » 03 Déc 2006, 11:57

Dominique Lefebvre a écrit:Et moi, je te dis pas! J'ai touché mon premier ordinateur (un IBM 370) à l'Ecole en 1977...
Ensuite les bijoux de calcul: HP1000 et VAX 1180


Le temps passe vraiment trop vite :triste: enfin remarque, c'est psychologique: plus tu vieillis, plus ton cerveau a emmagasiné de "souvenirs" (de vie, quoi); et la réaction se passe: plus tu vis, moins ton cerveau est marqué par les nouvelles infos. C'est pour ca que plus tu vieillis, moins tu ne te souviens des évènements journaliers. Seuls les trucs choquants laissent une trace. Le cerveau a donc l'impression qu'il ne s'est rien passé de spectaculaire, et donc rien n'est "gardé".

Par contre, j'ai oublié de qui vient cette théorie. Moi et la psychologie, ca fait 14 :briques:

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 6 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite