Bon alors suite a mes récentes recherches en ce qui concerne le codage sur les réseaux (client, serveur, socket, protocole , ...) j'ai décider de vous faire part de mais trouvaille dans un tuto.
Si vous avez un point d'ombre ou bien qu'une partie du tuto vous semble mal rédigé faites moi signe et j'essayerai de remédier a cela.
PS: Le tuto sera fait avec code::block sous window j'essayerai dans la mesure de le rendre compatible avec les autres IDE et linux dans la partie Annexe. -Sommaire : I-Introduction: A)Les réseaux. B)Un serveur. C)Un client.II-Relation client<->serveur: A)Théorie... B)Codage d'un serveur. C)Codage d'un client. D)Améliorations.III-Etude de différents protocoles: A)HTTP. B)IRC. C)POP3, SMTP, IMAP. D)FTP.IV-Annexe: A)Avec linux. B)Avec les autres IDE.I-Introduction:
A)Les réseaux:Voici la définition de réseau par
Wikipedia :
Un réseau informatique est un ensemble d'ordinateurs reliés entre eux pour échanger des informations.
Je pense que cette définition parle d'elle même

Voici un schémas un peu trivial de ce que peut être un réseau :

Un réseau est donc une multitude d'ordinateur reliés entre eux soir par des câbles ou par tout autre moyen (wifi, ...).
Sur un réseau, il y a deux type d'ordinateur, ce qui joue le rôle de serveur et les autres qui jouent le rôle de clients.
Un serveur et un client sont tous les deux des programmes.

Attention on appelle communément un serveur l'ordinateur destiner a faire fonction le programme serveur ce qui peut porter a confusion.
B)Un serveur.Un serveur est un programme qui reçoit des données de la part du client, qui les traites et qui renvoies ensuite des données.
On peut le schématiser ainsi:
Client->serveur: qu'elle heure est t-il ? (envoies des données)
le serveur regarde ça montre, puis répond: (traitement des données)
Serveur->client: 17h58. (envoies de données
On localise un serveur grâce a son adresse ip, de la forme
www.xxx.yyy.zzz.
Chaque adresse ip est unique, on ne peu pas la retrouver autre part.
Pour connaitre l'adresse ip d'un serveur (l'ordinateur pas le programme

), il suffit de faire un ping sur l'adresse :
C:\ping www.dev-fr.org
Envoi d'une requˆte 'ping' sur www.dev-fr.org [88.191.48.117] avec 32 octets de données:
Réponse de 88.191.48.117ÿ: octets=32 temps=55 ms TTL=54
Réponse de 88.191.48.117ÿ: octets=32 temps=55 ms TTL=54
Réponse de 88.191.48.117ÿ: octets=32 temps=54 ms TTL=54
Réponse de 88.191.48.117ÿ: octets=32 temps=54 ms TTL=54
Statistiques Ping pour 88.191.48.117:
Paquets : envoyés = 4, re‡us = 4, perdus = 0 (perte 0%),
Durée approximative des boucles en millisecondes :
Minimum = 54ms, Maximum = 55ms, Moyenne = 54ms
On peut lire en rouge, l'adresse IP du serveur.
Le problème qui vient maintenant est que sur un ordinateur, il peut avoir plusieurs serveur d'installer, par exemples il peut posséder un serveur
HTTP, un serveur POP & SMTP, et aussi pourquoi pas un serveur FTP.

Hola stop ! Comment fait ton pour savoir avec lequel communiquer


Deux minutes j'y vient...
Pour pouvoir communiquer avec le bon serveur, nous allons utiliser des ports.

Un port

c'est quoi ce truc encore


Un port c'est un peu comme une porte que possède ton pc. Imagine qu'il y est un serveur derrière chaque port. Et bien il te suffit de savoir quel port il utilise pour pouvoir communiquer avec lui

.
Chaque ordinateur possède 65536 ports. A chaque port, il ne peut y avoir qu'un serveur.
Vous pouvez voir la liste des ports spécifique pour des serveurs
iciles ports a connaitre pour la suite du tuto sont : HTTP, POP | SMTP | IMAP, FTP et IRC.
C)Un client.
Vous vous demandez bien ce que peut être un client hein ?

Et bien devinez quoi vous êtes en train d'en utiliser un, sans même le savoir

Et oui je parle de votre navigateur internet que ce soit Firefox, Internet Explorer, Safari, et j'en passe...
Comme je l'ai dit plus haut, un serveur reçoit les données d'un client, les interprètent, et renvoie d'autres données.
Et bien votre navigateur fait cela.Il demande au serveur qui héberge la page web si il peut l'avoir, le serveur lui envoie gentillement, et votre navigateur ce charge de l'afficher.
Bon évidement c'est un schémas très simplifié en faite pour faire cela votre navigateur utilise le protocole HTTP mais nous verrons ceci plus tard dans le tuto
II-Relation client<->serveur:
A)Théorie...Les relations clients client serveur sont relativement simple, ils suffit de les connecter et ensuite, ils peuvent s'échanger toutes sortes de données...
Pour ce faire nous allons utiliser la librairie WinSock2, une librairie bas niveau de window, elle a beau etre bas niveau elle n'en est pas pour autant plus difficile a manipuler...
Template :
(c):
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
int main()
{
WSADATA wsaData;
int err = 0;
//Initialisation de winsock
err = WSAStartup(MAKEWORD(2, 0), &wsaData);
if (err != NO_ERROR)
{
printf("WSAStartup failed !: %d\n", WSAGetLastError());
return 1;
}
/*******************************************
Votre code ici...
*******************************************/
//On quitte winsock en libérant la mémoire qu'il a alloué...
WSACleanup();
system("PAUSE");
return 0;
}
Ne pas oublier de linker la librairie winsock2, voir plus bas dans la partie Annexe...
Voici Une liste non exhaustive des fonctions les plus couramment utiliser avec winsock :
(c):
SOCKET WSAAPI socket(__in int af, __in int type, __in int protocol);//Creation de la socket...
Infos...(c):
int connect(__in SOCKET s, __in const struct sockaddr* name, __in int namelen); //Connection de la socket ...
Infos...(c):
int send( __in SOCKET s, __in const char* buf, __in int len, __in int flags);//Envoyer des donnees brutes (buffer)
Infos...(c):
int recv( __in SOCKET s, __out char* buf, __in int len, __in int flags);//Recevoir des donnees brutes (buffer)
Infos...(PS: pour les linuxien, voir Annexe...) B)Codage d'un serveur.Voici le squelette général d'un serveur, celui ci ce lance sur le port 23 de la machine local et attend un connection et dit lorsqu'un client c'est connecte:
(c):
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
int main()
{
WSADATA wsaData;
int err = 0;
SOCKET sock;
SOCKADDR_IN sin = {0};
int sin_size = sizeof(sin);
printf("Winsock Init...");
err = WSAStartup(MAKEWORD(2, 0), &wsaData);
if (err != NO_ERROR)
{
printf("FAILED !: %d\n", WSAGetLastError());
return 1;
}
else printf("DONE !\n");
printf("Creation de la socket...");
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//AF_INET = internet, SOCK_STREAM = donnees TCP, IPPROTO_TCP = protocole TCP/IP
if (sock == INVALID_SOCKET)
{
printf("FAILED !: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
else printf("DONE !\n");
printf ("\nLa socket %d est maintenant ouverte en mode TCP/IP\n", sock);
sin.sin_addr.s_addr = htonl (INADDR_ANY); // Accepter n'importe quelle ip entrante
sin.sin_family = AF_INET; // protocol familial (IP)
sin.sin_port = htons (23); // listage du port
printf("Ligature...");//Pour lier la socket aux infos du serveur
err = bind (sock, (SOCKADDR *) &sin, sin_size);
if (err == SOCKET_ERROR)
{
printf("FAILED !: %d\n", WSAGetLastError());
WSACleanup();
closesocket(sock);
return 1;
}
else printf("DONE !\n");
printf("Listage...");
// démarrage du listage (mode server)
err = listen (sock, 5);
if(err == SOCKET_ERROR)
{
printf("FAILED !: %d\n", WSAGetLastError());
WSACleanup();
closesocket(sock);
return 1;
}
else printf("DONE !\n");
printf ("Patientez pendant que le client se connecte sur le port %d...\n", htons(sin.sin_port));
sock = accept (sock, (SOCKADDR *) &sin, &sin_size);//fonction bloquante. Le reste du programme est en attente tant qu'il n'y a aucune connexion
printf ("Un client se connecte avec la socket %d de %s:%d\n", sock, inet_ntoa (sin.sin_addr), htons(sin.sin_port));
closesocket(sock);
WSACleanup();
system("PAUSE");
return 0;
}
Maintenant que notre serveur est près, il nous faut faire le client adéquat...
C)Codage d'un client.De même pour le client, on lui cree une socket sur le port 23, on ce connecte a notre serveur et dit si la tentative a échouée ou réussie.
(c):
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
int main()
{
WSADATA wsaData;
int err = 0;
SOCKET sock;
SOCKADDR_IN sin = {0};
printf("Winsock Init...");
err = WSAStartup(MAKEWORD(2, 0), &wsaData);
if (err != NO_ERROR)
{
printf("FAILED !: %d\n", WSAGetLastError());
return 1;
}
else printf("DONE !\n");
printf("Creation de la socket...");
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
printf("FAILED !: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
else printf("DONE !\n");
printf ("\nLa socket %d est maintenant ouverte en mode TCP/IP\n", sock);
sin.sin_addr.s_addr = inet_addr("127.0.0.1"); // Adresse IP localhost
sin.sin_family = AF_INET; // protocol familial (IP)
sin.sin_port = htons (23); // listage du port
// Si le client arrive à se connecté
if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
printf("Connexion a %s sur le port %d\n", inet_ntoa (sin.sin_addr), htons(sin.sin_port));
else
printf("Impossible de se connecter\n");
// On ferme la socket précédemment ouverte
closesocket(sock);
WSACleanup();
system("PAUSE");
return 0;
}
Maintenant pour tester, lancer tout d'abord le serveur, et debloquer le si le parfeu window le demande, et ensuite lancer le clent si tout ce passe bien, le serveur dit qu'il a recu une connection et le client dit qu'il a reussit a ce connecter.
D)Ameliorations.Maintenant que notre serveur et notre client fonctionnent en harmonie, on peut les faires echanger des données... Aller c'est parti !
On va rajouter ce petit morceau de code apres l'acceptation du client par le serveur, pour qu'il envoie un "Welcome !" au Client :
(c):
char *sendbuf = "Welcome !";
printf("Sending %s...", sendbuf);
err = send(sock, sendbuf, sizeof (sendbuf), 0);
printf("%d bytes sent!\n", err);
Voila maintenant le message lancé depuis le serveur nous allons tenter de le récupérer avec le client :
(c):
char recvbuf[1024];
memset(recvbuf, 0, sizeof(recvbuf));
printf("Receiving...");
do {
err = recv(sock, recvbuf, sizeof(recvbuf), 0);//fonction bloquante qui fige le programme tant qu'elle ne reçoit rien
} while (err <= 0);
printf("%d bytes received !\n%s\n", err, recvbuf);
A venir le multi-threading...III-Etude de différents protocoles:
A)HTTP.Voila maintenant que l'on sait comment fonctionne un serveur et un client, nous allons apprendre a utiliser des protocoles.

Qu'est ce que c'est ce truc

Ne vous inquiétez pas un protocole c'est très simple...
Par exemple, pour pouvoir parler a ta famille, tu utilise le français, par contre si tu veut parler a ton correspondant en français, il risque de ne rien comprendre...
Les protocoles c'est pareil, c'est le langage qu'utilise les serveurs et les clients pou pouvoir communiquer ensemble. Et si tu lui parle un autre langage, il ne comprendra pas et te le fera savoir
Généralement, les requêtes d'un protocoles sont de la forme :
[Methode] <arguments> \r\n Le mieux pour assimiler tout cela est de prendre un exemple concret, nous allons prendre le protocole HTTP (HyperText Transfert Protocol), car c'est le protocole le plus utiliser est aussi le plus simple. C'est lui qui permet de naviguer sur internet, vous ne vous êtes jamais demandé a quoi pouvez servir le "http://" dans la barre d'url de votre navigateur, ou bien lorsque vous faire précédent et qu'il vous dit que des données on etait envoyer par POST ? Et bien cette époque est révolue vous aller maintenant savoir ce qu'il en est...
Mise en forme d'un requête HTTP :
Méthode url HTTP/1.0\r\n
Champ1 : valeur 1\r\n
Champ2 : valeur 2\r\n
\r\n
Ceci est le corps de ma requête ... Les différentes méthode sont :
HEAD qui permet d'avoir l'entête d'une page web
GET qui permet l'entête et le corps d'une page web
POST qui permet d'avoir l'entête, le corps, mais aussi de passer des variables a la page php
Voici un code d'exemple qui permet de recevoir l'entete la page :
www.dev-fr.org/index.php(c):
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
int main()
{
WSADATA wsaData;
int err = 0;
SOCKET sock;
SOCKADDR_IN sin = {0};
char *sendbuf = "GET /index.php HTTP/1.1\r\nHost: www.dev-fr.org\r\n\r\n";
char recvbuf[1024];
printf("Winsock Init...");
err = WSAStartup(MAKEWORD(2, 0), &wsaData);
if (err != NO_ERROR)
{
printf("FAILED !: %d\n", WSAGetLastError());
return 1;
}
else printf("DONE !\n");
printf("Creation de la socket...");
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
printf("FAILED !: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
else printf("DONE !\n");
printf ("\nLa socket %d est maintenant ouverte en mode TCP/IP\n", sock);
sin.sin_addr.s_addr = inet_addr("88.191.48.117"); // Adresse IP www.dev-fr.org
sin.sin_family = AF_INET; // protocol familial (IP)
sin.sin_port = htons (80); // listage du port
// Si le client arrive à se connecté
if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
printf("Connexion a %s sur le port %d\n", inet_ntoa (sin.sin_addr), htons(sin.sin_port));
else
printf("Impossible de se connecter\n");
printf("Sending : \n%s", sendbuf);
err = send(sock, sendbuf, (int)strlen(sendbuf), 0);
printf("%d bytes sent !\n", err);
printf("Receiving...\n\n");
//shutdown(sock, SD_SEND);
do {
memset(recvbuf, 0, sizeof(recvbuf));
err = recv(sock, recvbuf, sizeof(recvbuf), 0);//fonction bloquante qui fige le programme tant qu'elle ne reçoit rien
printf("Bytes received : %d\n", err);
printf("\n%s\n", recvbuf);
} while (err > 0);
printf("Connexion closed !\n");
// On ferme la socket précédemment ouverte
closesocket(sock);
WSACleanup();
system("PAUSE");
return 0;
}

La connexion doit etre effectué sur le port 80, qui est le port par defaut de tous les serveur HTTP.
Ne pouvant pas traiter tous les cas, pour plus d'informations, suivre ce
lien.

Ce protocole a tout de meme une particularite, une fois l'envoie de données termine, la connection est coupe. Tandis qu'avec les autres protocoles, les connection reste etablie jusqua ce le client la coupe ou bien apres un long moment d'innactivite.
B)IRC.
Pour les protocole suivant, nous allons utiliser l'utilitaire telnet de window pour pouvoir comprendre les principes de ces protocole.
Pour utiliser telnet, faite Démarrer>Exécuter...>telnet
Vous voila maintenant pres a utiliser telnet...
(PS: toutes les données envoyr depuis telnet ne sont pas chiffrées...)Pour commencer, on ouvre la connection entre telnet et le serveur :

irc.Prison.net étant le nom du serveur et 6667, le port associe au protocole IRC (Internet Relay Chat protocol).
Vous voila maintenant connecté au serveur, vous devriez voir 5 lignes apparaitre.
Vous pouvez maintenant commencer la procedure d'identification :
USER real_name "localhost" "irc.prison.net" :nickname

Telnet ajoute tout seul les "\r\n" a la fin de la requête, a ne pas omettre lors d'un programme...
après cela vous êtes identifié sur le serveur, vous recevez le MOTD, et vous pouvez utiliser toutes les commandes IRC disponible, par exemple :
Vous voyez la liste des personne présentes sur le chan.
Maintenant pour quitter la connection il suffit de faire :
Pour plus d'informations, suivre ce
lien.
C)POP3, SMTP, IMAP.C'est trois protocoles servent pour l'envoie et réception de courriers électroniques.
POP3 (Post Office Protocol version 3) permet de lire les e-mail, ainsi que IMAP (Internet Message Access Protocol) qui est un protocole assez récent, il n'est donc pas supporté beaucoup.
Et le protocole SMTP(Simple Mail Transfer Protocol).
Les ports par défaut sont :
- POP3 : 110
- SMTP : 25
- IMAP : 143
Envoie d'un mail avec telnet :
o smtp.orange.fr 25
EHLO hello //pour faire signe que nous sommes bien là
MAIL FROM: <xxx@xxx.xx>
RCPT TO: <xxx@xxx.xx>
DATA
Voici un beau mail pour tester le smtp avec telnet :)//passer ligne
.//écrire un point et repasser une ligne signe de la fin du message
QUIT
Pour plus d'informations, suivre ce
lien.
Voila vous venez d'envoyer un mail, maintenant on va aller le lire : c'est parti !
Reception d'un mail avec telnet :
Avec POP3 :
o pop.orange.fr 110
USER user.name //tout ce qu'il y a avant le @ de l'adresse mail en question
PASS *******
LIST //donne le nombre de messages ainsi que leurs taille
TOP 1 0 //récupère tout l'entête du premier message
RETR 1 //récupère tout le message
QUIT //ferme la connection
Pour plus d'informations, suivre ce
lien.
Ou bien avec IMAP :
o imap.orange.fr 143
a001 login nicolas ****** //login avec nom d'utilisateur/mot de passe
a002 select inbox //on selectionne sa mailbox
a002 FETCH 1 full //on recupere les informations sur le message
a002 FETCH 1 BODY[TEXT] // on recupere le contenu du message
a002 logout //on sort
Pour plus d'informations, suivre ce
lien.
Autres informations relatives :
ici.
D)FTP.Le protocole FTP (File Transfer Protocol) quant a lui est différent des autres protocoles. En effet il n'utilise pas 1 mais 2 ports...
Le premier port : le PI (Protocol Interpreter, port 21) permet de dialoguer avec le serveur FTP.
Le second port : le DTP (Data Transfer Process, port 22) permet le transfert de fichier ASCII ou binaire.
Je ne vais pas faire de session telnet mais le principe reste le meme que pour tous les autres protocoles..
Pour plus d'informations, suivre ce
lienIV-Annexe:
A)Avec linux.Voici le template qui va bien pour nos chers amis linuxien :
(c):
#include <stdio.h>
#include <stdlib.h>
/**********************/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(sock) close (sock)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#endif
/*équivalent linux de winsock2*/
int main()
{
return 0;
}
B)Avec les autres IDE. Avec
Code::Block pour pouvoir utiliser la lib winsock2 vous devez linker la librairie correspondante :
Projects>Build Options>Linker>Add>C:\Program Files\CodeBlocks\lib\libws2_32.a
Ne pas mettre en relative path.
A venir... Réglage pour les différents IDEVoila que ce termine ce tuto, du moins pour le moment car je rajouterai des informations au fur est a mesure que l'on me le précise ou bien pour rajouter des informations complémentaires.
J'espère que vous avez pris plaisir a lire ce tuto, qui je doit le dire ma pris un certain temps a l'ecrire.
Voici une liste partiel des sites dont je me suis inspire :
Et je remercie T4ils qui a relut le tuto est ajouter quelques modifications.
Voila c'est a vous de jouer maintenant...