Soket sous LINUX

[Résolu]
Signaler
Messages postés
17
Date d'inscription
mercredi 15 mai 2013
Statut
Membre
Dernière intervention
13 juin 2006
-
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
-
Bonjour à tous le monde,

comme le nom l'indique, cela va parler de soscket sous linux (en C++). Il aut savoir que je travaille en mode connecté.

Je cherche un programme permettant de dialoguer entre deux application
entre deux PC ; un client et un serveur (une application par PC).



J'ai lu les méthodes a utiliser :

- Création de la socket : sockaddr_in //initialise la socket

- Identifiaction de la station du serveur avec struct hostent gethostbyname(* name)

- Création de la socket : socket(domaine, type, protocole)

- demande de la connection : int connect (sock, adrss,lg_ag)
- dialogue serveur/client :

- fermeture de la socket :



Les questions que je me pose sont :

- Je ne connait pas la fonction pour fermet la socket ?

- pour dialoguer serveur/client, il faut juste utilisé les fonctions recv() et send() ?

- Faut il faire un attachement de la soket avec la fonction bind() ?



Merci de vos réponses futures et a bientot

13 réponses

Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Si tu veux te servir des string en C, c mort.
String est une class de la STL, utilisé en C++. En C++ tu a besoin d'un include pour utiliser les string : .
Mais ne compte pas pouvoir t'en servir en C, il faut que tu utilise ce bon vieu char.

De plus fprintf ne marche pas, c'est printf("Taper votre trame \n"); ou fprintf(stdout,"Taper votre trame \n");

#define MAX_SIZE 65535

char a[MAX_SIZE] = " ";
ou
char* a=(char*)malloc(sizeof(char)*MAX_SIZE)

printf("Taper votre trame \n");
scanf("%s",a)
fflush(stdin);
strcpy(msg.corps, a);

TuRn3r
Messages postés
12
Date d'inscription
mardi 7 janvier 2003
Statut
Membre
Dernière intervention
12 septembre 2006

1. Pour fermer la socket : close(descripteur);

2. Pour le dialogue, tu peux utiliser read et write (en TCP), aucune idee pour recv et send mais je crois que ça marche (a confirmer)

3. Pour le bind, tu dois le faire explicitement pour le serveur, mais il sera fait implicitement pour le client

Petite remarque, gethostbyname() n'est pas necessaire, tu peux ecouter sur toutes les interfaces en faisant serveur_adr.sin_addr.s_addr INADDR_ANY;, ou sinon inet_addr("127.0.0.1"); suffit
Messages postés
12
Date d'inscription
mardi 7 janvier 2003
Statut
Membre
Dernière intervention
12 septembre 2006

ola, on dirait qu'il aime pas mes sauts de ligne...
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
Bonjour,

Voila un petit squelette de communication par socket en mode connecté :

myinet.h :

#define MYCORPS 16
struct mymsg {
uint32_t entete;
char corps[MYCORPS];
};

#define BACKLOG 64

recepteur :

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include "myinet.h"

main (int argc, char *argv[]) {

int sockfd, socksrvfd;
struct sockaddr_in my_addr, name, from;
int fromlen;
struct mymsg msg;
int ret_recv;
int cpt = 0, i, j;

if (argc < 2) { fprintf(stderr, "Usage : afinettcpr port_reception\n"); exit (EXIT_FAILURE);}

/* Acquisition d'un descripteur de socket. */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) { perror("socket()"); exit (EXIT_FAILURE); }

/* assignation d'une adresse à la socket */
memset(&my_addr, '\0', sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons((uint16_t)atoi(argv[1]));
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1) { perror("bind()"); exit(EXIT_FAILURE); }
if (listen(sockfd, BACKLOG) == -1) { perror("listen()"); exit(EXIT_FAILURE); }

/* socket de service */
fromlen = sizeof(from);
memset(&from, '\0', sizeof(from));

ecoute:
socksrvfd = accept(sockfd, (struct sockaddr*)&from, &fromlen);
if (socksrvfd == -1) { perror ("accept()"); exit(EXIT_FAILURE); }
/* qui a émis */
printf("fromlen : %d ", fromlen);
printf("sin_family : %d ", from.sin_family);
printf("sin_port : %d ", from.sin_port);
printf("sin_addr : %d ", inet_ntoa(from.sin_addr));
printf("\n");
printf("Entrée dans la boucle de reception\n");
while (++cpt) {
/* lecture d'un message */
ret_recv = recv(socksrvfd, &msg, sizeof(msg), 0);
if (ret_recv == 0) goto ecoute;
if (ret_recv == -1) { perror("recv()"); exit (EXIT_FAILURE); }
/* message reçu */
printf("cpt_serveur %d : ", cpt);
printf("message %d - %s ",(int)ntohl(msg.entete), msg.corps);
printf("\n");
}
}

emetteur :

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include "myinet.h"

main (int argc, char *argv[]) {

struct hostent *phost;
int sockfd;
struct sockaddr_in serv_addr;
int cpt = 0;
struct mymsg msg;
int ret_send;
if (argc < 3) {
fprintf(stderr, "USAGE : afinettcpe machine_cible port_cible\n");
exit (EXIT_FAILURE);
}
phost = gethostbyname(argv[1]);
if (phost == NULL) {
fprintf(stderr, "Incident gethostbyname("%s"p)", argv[1]);
}

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) { perror("socket()"); exit (EXIT_FAILURE); }

/* pour le client un bind est fait automatiquement lors du connect() */
memset(&serv_addr, '\0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons((uint16_t)atoi(argv[2]));
memcpy(&serv_addr.sin_addr, phost->h_addr, phost->h_length);
if (connect (sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1 ) { perror ("connect()"); exit(EXIT_FAILURE); }

while (++cpt) {
msg.entete = htonl((uint32_t)cpt);
strcpy (msg.corps, "Pour voir");
ret_send = send(sockfd, &msg, sizeof(msg), 0);
if (ret_send == -1) { perror ("send()\n"); exit(EXIT_FAILURE); }
sleep(1);
}
}

Pour la fermeture de socket. Il s'agit d'un fichier comme un autre. Une ressource du programme qui sera libérée avec toutes les autres. Il n'est pas necessaire de faire un close, s'il n'est pas utile.
Messages postés
17
Date d'inscription
mercredi 15 mai 2013
Statut
Membre
Dernière intervention
13 juin 2006

Merci pour vos réponse mais j'ai un doute : je doit mettre le code de l'emetteur (client) et du recpeteur (serveur) dans un même fichier.cpp ou dans deux fichiers séparés ?

Une autre question pour toi AlexN : j ai pas compris ou il faut meetre ce bout de code :

myinet.h :
#define MYCORPS 16struct mymsg{
uint32_t entete;
char corps[MYCORPS];
};

#define BACKLOG 64

Merci de vos reponses futures et à bientôt
Messages postés
12
Date d'inscription
mardi 7 janvier 2003
Statut
Membre
Dernière intervention
12 septembre 2006

Tu dois avoir 3 fichiers : 2 .cpp et un myinet.h dans le meme repertoire.
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
Oui,

puis compilation :

cc emetteur.c -o e
cc recepteur.c -o r

Pour tester en local,
Lancer le recepteur en arrière plan (ici port 2) :
r 2 &
Lancer l'emetteur :
e localhost 2
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Salut, si ca peut t'aider, va jeter un oeuil sur une de mes sources
http://www.cppfrance.com/codes/ECHANGE-FICHIER-AVEC-SERVEUR-MULTICLIENT_30629.aspx

TuRn3r
Messages postés
17
Date d'inscription
mercredi 15 mai 2013
Statut
Membre
Dernière intervention
13 juin 2006

Merci pour vos programmes, cela marche a merveille mais j'ai encore un tout petit souci :

je lance au plan arriere le recepteur, puis je lance l emetteur, donc le recepteur marque

cpt_serveur 96 : message 88 - Pour voir, ainsi de suite...



Cela veut dire quoi ?

Si je marque un message dans la console de l'emtteur, cela vas apparaitre ou ?



Merci encore une fois et merci de vos réponses futures



PS : il fallait dire que les programmes marche qu'en super utilisateur ^^
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Il faut pas que tu lance le recepteur en arriere plan (avec un &) car tu peux plus avoir acces à la console.
Lance 2 consoles. Une avec l'emetteur et une avec le recepteur.

TuRn3r
Messages postés
17
Date d'inscription
mercredi 15 mai 2013
Statut
Membre
Dernière intervention
13 juin 2006

Salut a tous,



Ala place du While(++cpt) dans l'emetteur.c, j'ai remplacé ce bout de
code : il permet a l'utilisateur de taper une trame(chaine de
caractère) et donc d'afficher cette trame dans la console du recpeteur,
mais j'ai un probleme avec le scanf.



char * a;



<meta http-equiv= "Content-Type" content="text/html; charset=UTF-8">
<meta name="Generator" content="Kate, the KDE Advanced Text Editor">

printf("Taper votre trame \n");

scanf("%c",&a);

printf("%c \n",a);

strcpy (msg.corps, a);
ret_send = send(sockfd, &msg, sizeof (msg), 0);
if (ret_send == -1) { perror ("send()\n"); exit(EXIT_FAILURE); }
sleep(1);


En fait, ce que j'ai envie de faire c'est d'envoyer une trame au recepteur et de l'afficher.



Merci de vos réponses et a bientot
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
char *a;
scanf (..., &a);

Tu donnes a scanf l'adresse d'un pointeur sur char pas d'un char.

char a;
scanf(...,&a);
strcpy (msg.corps, &a)

Si tu disposes d'un shell avec job control, tu pourras également faire basculer les tâches depuis une unique console.
Messages postés
17
Date d'inscription
mercredi 15 mai 2013
Statut
Membre
Dernière intervention
13 juin 2006

Merci pour ta réponse, j'ai essayer avec une nouvelle méthode :



#include <string.h>



string a = " ";

fprintf("Taper votre trame \n");

scanf("%s",a)

strcpy(msg.corps, &a);



Mon but est d'arriver à taper une trame (c'est une chaine de caractères avec des chiffres et des nombres), et ensuite que cette

trame soit envoyé et afficher par le récepteur.

J'ai essayer de le faire avec un string, mais en C, le compilateur connait le string ?

Quelles sont les erreurs dans mon petit bout de programme car il ne reconnait pas string ?



Merci de vos réponse futures et @ bientôt.