Exemple de serveur et client avec sockets C sous Linux – BinaryTides – Serveur d’impression

Dans un exemple précédent, nous avons appris les bases de la programmation de socket en C. Dans cet exemple, nous allons construire un client et un serveur ECHO de base. Le serveur / client illustré ici utilise des sockets TCP ou SOCK_STREAM.

Les sockets TCP sont orientées connexion, ce qui signifie qu'elles ont un concept de connexion indépendante sur un certain port qu'une application peut utiliser à la fois. Le concept de connexion fait de TCP un flux "fiable" tel que si des erreurs se produisent, elles peuvent être détectées et compensées en renvoyant les paquets en échec.

Serveur

Permet de construire un serveur Web très simple. Les étapes pour créer un serveur Web sont les suivantes:

1. Créer un socket
2. Lier à l'adresse et au port
3. Mettez en mode d'écoute
4. Acceptez les connexions et procédez-y ensuite.

Exemple rapide

/ *
Exemple de serveur de socket C
* /

#comprendre
#comprendre	// strlen
#comprendre
#comprendre	// inet_addr
#comprendre	//écrire

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

int socket_desc, client_sock, c, read_size;
struct sockaddr_in serveur, client;
char client_message[2000];

// Créer un socket
socket_desc = socket (AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1)

printf ("Impossible de créer un socket");

met ("Socket créé");

// Préparez la structure sockaddr_in
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons (8888);

//Lier
if (bind (socket_desc, (struct sockaddr *) & server, sizeof (server)) <0)

// affiche le message d'erreur
perror ("Échec de la liaison. Erreur");
retour 1;

met ("bind done");

//Ecoutez
écouter (socket_desc, 3);

// Accepter et connexion entrante
met ("En attente de connexions entrantes ...");
c = sizeof (struct sockaddr_in);

// accepte la connexion d'un client entrant
client_sock = accepter (socket_desc, (struct sockaddr *) & client, (socklen_t *) & c);
if (client_sock < 0)
	
		perror("accept failed");
		return 1;
	
	puts("Connection accepted");
	
	//Receive a message from client
	while( (read_size = recv(client_sock , client_message , 2000 , 0)) > 0)

// Renvoie le message au client
write (client_sock, client_message, strlen (client_message));


if (read_size == 0)

met ("Client déconnecté");
fflush (stdout);

sinon si (read_size == -1)

perror ("recv failed");


retourner 0;

L'exemple de code ci-dessus démarrera un serveur sur le port 8888 de l'hôte local (127.0.0.1)
Une fois qu'il reçoit une connexion, il lira certaines entrées du client et répondra avec le même message.
Pour tester le serveur, exécutez le serveur, puis connectez-vous à partir d'un autre terminal à l'aide de la commande telnet comme celle-ci

$ telnet localhost 8888

Client

Maintenant, au lieu d'utiliser le programme telnet en tant que client, pourquoi ne pas écrire notre propre programme client. Encore assez simple

/ *
Exemple de client C ECHO utilisant des sockets
* /
#comprendre	// printf
#comprendre	// strlen
#comprendre	//prise
#comprendre	// inet_addr

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

chaussette int;
serveur struct sockaddr_in;
message char[1000] , server_reply[2000];

// Créer un socket
chaussette = socket (AF_INET, SOCK_STREAM, 0);
if (chaussette == -1)

printf ("Impossible de créer un socket");

met ("Socket créé");

server.sin_addr.s_addr = inet_addr ("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons (8888);

// Se connecter au serveur distant
if (connect (sock, (struct sockaddr *) & server, sizeof (server)) <0)

perror ("échec de connexion. Erreur");
retour 1;


met ("Connecté  n");

// continue de communiquer avec le serveur
tandis que (1)

printf ("Entrez le message:");
scanf ("% s", message);

// Envoyer des données
if (envoyer (chaussette, message, strlen (message), 0) <0)

met ("Échec de l'envoi");
retour 1;


// Recevoir une réponse du serveur
if (recv (sock, server_reply, 2000, 0) <0)

met ("recv a échoué");
Pause;


met ("Réponse du serveur:");
met (server_reply);


fermer (chaussette);
retourner 0;

Le programme ci-dessus se connectera au port localhost 8888 et demandera ensuite des commandes à envoyer. Voici un exemple, à quoi ressemblerait la sortie

$ gcc client.c && ./a.out
Prise créée
Lié

Entrez le message: salut
Réponse du serveur:
salut
Entrez un message: comment allez-vous

Serveur pour gérer plusieurs connexions

Le serveur dans l'exemple ci-dessus présente un inconvénient. Il peut gérer la communication avec un seul client. Ce n'est pas très utile. Une façon de contourner ce problème consiste à utiliser des threads. Un thread peut être attribué à chaque client connecté qui gérera la communication avec le client.

Exemple de code

/ *
Exemple de serveur de socket C, gère plusieurs clients à l'aide de threads
* /

#comprendre
#comprendre	// strlen
#comprendre	// strlen
#comprendre
#comprendre	// inet_addr
#comprendre	//écrire
#comprendre // pour le filetage, lien avec lpthread

// la fonction thread
void * connection_handler (void *);

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

int socket_desc, client_sock, c, * new_sock;
struct sockaddr_in serveur, client;

// Créer un socket
socket_desc = socket (AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1)

printf ("Impossible de créer un socket");

met ("Socket créé");

// Préparez la structure sockaddr_in
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons (8888);

//Lier
if (bind (socket_desc, (struct sockaddr *) & server, sizeof (server)) <0)

// affiche le message d'erreur
perror ("Échec de la liaison. Erreur");
retour 1;

met ("bind done");

//Ecoutez
écouter (socket_desc, 3);

// Accepter et connexion entrante
met ("En attente de connexions entrantes ...");
c = sizeof (struct sockaddr_in);


// Accepter et connexion entrante
met ("En attente de connexions entrantes ...");
c = sizeof (struct sockaddr_in);
while ((client_sock = accept (socket_desc, (struct sockaddr *) & client, (socklen_t *) & c))))

met ("Connexion acceptée");

pthread_t sniffer_thread;
new_sock = malloc (1);
* new_sock = client_sock;

if (pthread_create (& sniffer_thread, NULL, connection_handler, (void *) new_sock) <0)

perror ("impossible de créer un thread");
retour 1;


// Rejoignez maintenant le thread, afin de ne pas terminer avant le thread
// pthread_join (sniffer_thread, NULL);
met ("Gestionnaire affecté");


if (client_sock < 0)
	
		perror("accept failed");
		return 1;
	
	
	return 0;


/*
 * This will handle connection for each client
 * */
void *connection_handler(void *socket_desc)

	//Get the socket descriptor
	int sock = *(int*)socket_desc;
	int read_size;
	char *message , client_message[2000];
	
	//Send some messages to the client
	message = "Greetings! I am your connection handlern";
	write(sock , message , strlen(message));
	
	message = "Now type something and i shall repeat what you type n";
	write(sock , message , strlen(message));
	
	//Receive a message from client
	while( (read_size = recv(sock , client_message , 2000 , 0)) > 0)

// Renvoie le message au client
write (sock, client_message, strlen (client_message));


if (read_size == 0)

met ("Client déconnecté");
fflush (stdout);

sinon si (read_size == -1)

perror ("recv failed");


// Libère le pointeur de socket
gratuit (socket_desc);

retourner 0;

Exécutez le serveur ci-dessus et connectez-vous à partir de plusieurs clients et il les gérera tous. Il existe d'autres façons de gérer plusieurs clients, comme la sélection, le sondage, etc. Nous en parlerons dans un autre article. Till puis pratiquez les exemples de code ci-dessus et profitez-en.

Dernière mise à jour le: 27 novembre 2012

Laisser un commentaire