Utilisateur anonyme
-
23 oct. 2009 à 21:29
Utilisateur anonyme -
10 févr. 2010 à 10:23
Salut à tous,
Me voici me voila, venant humblement implorer votre aide ^^
Comme dit dans le titre, je dois pour un TP de Réseaux et Protocoles créer 2 programmes, un client et un serveur pour discuter a plusieurs hé ouais la classe ;-) Windows Live Messenger tiens-toi bien j'arrive XD
Sauf que ! J'y arrive pas trop trop quoi...
En fait le client doit se connecter sur le serveur (qui ouvre un port choisi en ligne de commande, en fait on est sur le réseau de l'université); dès le lancement on peut écrire (sur l'entrée standard) notre message, qui sera envoyé au serveur (a priori après appui de la touche Entrée lol) dont le role est, après réception du message d'un client, de le renvoyer a tous les clients (sauf l'envoyeur) qui l'afficheront ensuite...
Bon par contre j'ai fait en sorte de faire afficher le message AUSSI par le serveur, pour voir si ça marchait bien, etc...
Le truc marrant en plus, c'est que pour faire ça on est OBLIGES d'utiliser la fonction select autant pour le client que pour le serveur(hé oui pas de fork ni de thread, on a pas le droit héhé), fonction que je ne critique pas bien sur non mais p***** de fonction de m?#!* !!!
Alors mon code compile (yeah victoire !), et fonctionne a moitié : le serveur a l'air de fonctionner comme il faut, mais le client, et d'une, m'affiche un truc a l'infini croyant que le serveur lui a envoyé un truc (c'est deja un truc que je comprends pas), et de 2 n'affiche pas la chaine qu'un autre client a envoyé alors que le serveur a a priori renvoyé la chaine aux autres clients (2ème incompréhension ^^).
D'ailleurs voici 2 screenshots des terminaux que j'ouvre et ou je lance les 2 progs :
http://img12.imageshack.us/img12/4172/shot1rp.jpg
http://img190.imageshack.us/img190/2774/shot2q.jpg
Et donc, voici en avant-premiere le code commenté du successeur de WLM ^^
serveur :
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int sockfd, sockfd2; // descripteurs de socket
fd_set readfds; // ensemble des descripteurs en lecture qui seront surveilles par select
int t[FD_SETSIZE]; // tableau qui contiendra tous les descripteurs de sockets, avec une taille egale a la taille max de l'ensemble d'une structure fd_set
int taille=0; // nombre de descripteurs dans le tableau precedent
char buf[1024]; // espace necessaire pour stocker le message recu
memset(buf,'\0',1024); // initialisation du buffer qui sera utilisé
struct sockaddr_in my_addr; // structure d'adresse qui contiendra les param reseaux du recepteur
struct sockaddr_in client; // structure d'adresse qui contiendra les param reseaux de l'expediteur
// taille d'une structure sockaddr_in utile pour la fonction recvfrom
socklen_t sin_size = sizeof(struct sockaddr_in);
// verification du nombre d'arguments sur la ligne de commande
if(argc != 2)
{
printf("Usage: %s port_local\n", argv[0]);
exit(-1);
}
// creation de la socket
sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
// initialisation de la structure d'adresse du serveur (pg local)
// famille d'adresse
my_addr.sin_family = AF_INET;
// recuperation du port du serveur
my_addr.sin_port = ntohs(atoi(argv[1]));
// adresse IPv4 du serveur
my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
// association de la socket et des param reseaux du serveur
if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(my_addr)) != 0)
{
perror("Erreur lors de l'appel a bind -> ");
exit(1);
}
// indication de la limite MAX de la file d'attente des connexions entrantes
if(listen(sockfd,10) != 0)
{
perror("Erreur lors de l'appel a listen -> ");
exit(2);
}
printf("Attente de connexion\n");
t[0]=sockfd; // on ajoute deja la socket d'ecoute au tableau de descripteurs
taille++; // et donc on augmente "taille"
while(1){
FD_ZERO(&readfds); //il faut remettre tt les elements ds readfds a chaque recommencement de la boucle, vu que select modifie les ensembles
int j;
int sockmax=0;
for(j=0;j<taille;j++){
if(t[j] != 0)
FD_SET(t[j],&readfds); // on remet donc tous les elements dans readfds
if(sockmax < t[j]) // et on prend ici le "numero" de socket maximal pour la fonction select
sockmax = t[j];
}
if(select(sockmax+1,&readfds,NULL,NULL,NULL) == -1){ // on utilise le select sur toutes les sockets y compris celle d'ecoute
perror("Erreur lors de l'appel a select -> ");
exit(1);
}
if(FD_ISSET(sockfd,&readfds)){ // si la socket d'ecoute est dans readfds, alors qqch lui a ete envoye (=connection d'un client)
if((sockfd2 = accept(sockfd,(struct sockaddr*)&client,&sin_size)) == -1){ // on accepte la connexion entrante et on cree une socket...
perror("Erreur lors de accept -> ");
exit(3);
}
printf("Connexion etablie avec %s\n", inet_ntoa(client.sin_addr));
taille++; // ...qui est donc ajoutee au tableau de descripteurs
t[taille-1]=sockfd2;
}
int i;
for(i=1;i<taille;i++){ // on parcourt tous les autres descripteurs du tableau
if(FD_ISSET(t[i],&readfds)){ // si une socket du tableau est dans readfds, alors qqch a ete envoye au serveur par un client
if(recv(t[i],&buf,1024,0) == -1){ // on stocke alors le message
perror("Erreur lors de la reception -> ");
exit(4);
}
printf("La chaine recue est: %s\n",buf); // et on l'affiche
int k;
for(k=1;k<taille;k++){ // puis on l'envoie a tous les clients...
if(k != i){ // ...sauf l'envoyeur
if(send(t[k],&buf,1024,0) == -1){
perror("Erreur lors de l'appel a send -> ");
exit(1);
}
}
}
} // reste donc a resoudre le probleme de supprimer la socket du tableau, et modifier "taille"...
}
}
}
client :
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int sockfd; // descripteur de socket
struct sockaddr_in serveur; // structure d'adresse qui contiendra les param reseaux du serveur
fd_set readfds; // ensemble des descripteurs en lecture qui seront surveilles par select
char buf[1024]; // espace necessaire pour stocker le message recu
char buf2[1024]; // espace necessaire pour envoyer un message au serveur
memset(buf,'\0',1024); // initialisation du buffer qui sera utilisé
memset(buf2,'\0',1024); // initialisation de l'autre buffer qui sera utilisé
// verification du nombre d'arguments sur la ligne de commande
if(argc != 3)
{
printf("Usage: %s @serveur port_serveur\n", argv[0]);
exit(-1);
}
// creation de la socket
sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
// initialisation de la structure d'adresse du serveur :
// famille d'adresse
serveur.sin_family = AF_INET;
// recuperation de l'adresse IPv4 du serveur
inet_aton(argv[1], &(serveur.sin_addr));
// recuperation du port du serveur
serveur.sin_port = htons(atoi(argv[2]));
printf("Tentative de connexion\n");
// tentative de connexion
if(connect(sockfd,(struct sockaddr*)&serveur,sizeof(serveur)) == -1)
{
perror("Erreur de connexion -> ");
exit(2);
}
printf("Connexion etablie\n");
while(1){
memset(buf,'\0',1024); // on reinitialise les buffers qui seront utilises
memset(buf2,'\0',1024);
FD_ZERO(&readfds); // il faut remettre tt les elements ds readfds a chaque recommencement de la boucle, vu que select modifie les ensembles
FD_SET(0,&readfds); // on rajoute l'entree standard
FD_SET(sockfd,&readfds); // on rajoute la socket de communication avec le serveur
if(select(sockfd+1,&readfds,NULL,NULL,NULL) == -1){
perror("Erreur lors de l'appel a select -> ");
exit(1);
}
if(FD_ISSET(0,&readfds)){ // si l'entree standard est dans readfds, alors l'utilisateur en en train de rédiger un message a envoyer
if(read(0,buf2,1024) == -1){ // on lit donc ce qui arrive sur l'entrée standard
perror("Erreur lors de l'appel a read -> ");
exit(1);
}
if(send(sockfd,buf2,1024,0) == -1){ // puis on l'envoie au serveur
perror("Erreur lors de l'appel a send -> ");
exit(1);
}
}
if(FD_ISSET(sockfd,&readfds)){ // si la socket de communication est dans readfds, alors le serveur nous a envoye un message
if(recv(sockfd,&buf,1024,0) == -1){
perror("Erreur lors de la reception -> ");
exit(4);
}
printf("La chaine recue est: %s\n",buf); // on l'affiche
}
}
}
J'ai essayé de commenter le mieux que je puisse...
Voila voila, donc je remercie par avance les courageux qui se plongeront dans mon code et qui pourront me dire ou est le probleme....ou plutot ou sont les problèmes :), je vous en serais vraiment très très très reconnaissant ^^
Mais de toute façon je suis preneur de toute remarque me permettant de m'améliorer !
dodoecchi
Messages postés454Date d'inscriptionsamedi 9 septembre 2006StatutMembreDernière intervention26 avril 201229 23 oct. 2009 à 23:50
Quelles études tu fais?
je suis en 1ere année d'IUT Réseaux et télécommunications
je vais faire ça aussi? ou c'est le departement informatique d'à côté ?
En fait la je suis en 3ème année de Licence d'informatique a Strasbourg ^^
Et pour ce qui est de l'IUT, ben je sais pas trop moi lol
On vous apprend à programmer ou pas ? Si oui, y'a de fortes chances pour que tu fasses ça un jour ou l'autre
(ce serait un comble qu'un IUT en réseaux ne voie pas les sockets :), mais tes profs te répondront surement mieux que moi...