Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Dans ce chapitre vous apprendrez presque tout sur l'histoire des sockets.
Vous verrez comment elles fonctionnent mais aussi quand et pourquoi elles ont été créées.
Nous nous attaquerons ensuite à la partie préprocesseur du code qui nous sera indispensable par la suite dans tous les projets avec des sockets.
Les sockets ont été mises au point en 1984, lors de la création des distributions BSD (
Berkeley Software Distribution). Apparues pour la première fois dans les systèmes
UNIX, les sockets sont des points de terminaison mis à l'écoute sur le
réseau, afin de faire transiter des données logicielles.
Celles-ci sont associées à un numéro de
port.
Les ports sont des numéros allant de 1 à 2
16 (soit 65536

). Chacun de ces ports est associé à un programme.
Les sockets sont aussi associées à un
protocole. Vous avez sûrement déjà entendu parler des protocoles
UDP/IP et
TCP/IP, sinon renseignez-vous

. Dans notre cas nous utiliserons le protocole TCP/IP.
Les sockets servent à établir une transmission de flux de données (
octets) entre deux machines ou applications.
C'est bien tout ça, mais à quoi ça sert exactement

?
Eh bien en C, vous avez sûrement plus d'une fois eu besoin d'un moyen de communication entre deux programmes, non ?
Dans ce cas on utilise parfois des fichiers qui servent de "passerelle"

, mais on passe souvent à côté des sockets qui peuvent le faire aussi bien

(je dirai même mieux

).
Le principal atout des sockets est que les informations sont transmises directement au programme voulu en plus d'être plus securisées que les fichiers.
Elles servent bien plus qu'on ne le pense...
Par exemple, le langage
PHP illustre très bien les sockets, car il utilise ce principe "Client / Serveur".
Ou bien même, quand vous naviguez sur Internet dans une page
HTML, votre navigateur va utiliser les sockets pour demander au serveur le
code source de la page, pour pouvoir afficher ce qu'elle contient :
Ce schéma est TRES simplifié ! Il n'est pas complet, mais permet d'avoir une vision simplifiée du principe. Pour le moment nous nous contenterons de cela.
Elles servent aussi pour tout ce qui touche au
réseau.
Vous voyez donc que les exemples sont multiples; je ne les citerai pas tous

.
Les sockets ne s'utilisent pas de manière identique selon les différents systèmes d'exploitation : je vais donc vous guider tout le long de ce chapitre pour que vous ne quittiez pas le bon chemin

.
Les inclusions et les ressources
Sur Windows
Tout d'abord, n'oubliez pas, dans
chaque projet que vous créez, d'ajouter le fichier
"wsock32" dans votre éditeur de liens. Vous trouverez ce fichier dans le dossier
"lib" de votre IDE. J'insiste un peu, car on oublie très souvent de le faire

.
Il faut savoir que presque tout ce qui touche aux sockets Windows se trouve dans le fichier
"winsock2.h", dans le dossier
header de votre IDE. Celui-ci est un fichier standard, il n'y a pas besoin de le télécharger

.
Nous allons donc tout de suite l'inclure dans notre premier programme comme suit :
Code : C
En général, vous aurez besoin des fichiers standards
"stdio.h" et
"stdlib.h".
Nous allons donc aussi les inclure :
Code : C1
2
3 | #include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
|
Vous devrez ajouter, dans le début de votre fonction
main, le code suivant pour pouvoir utiliser les sockets sous Windows :
Code : C1
2 | WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);
|
La fonction
WSAStartup sert à initialiser la bibliothèque WinSock. La macro MAKEWORD renseigne la bibliothèque sur la version que l'utilisateur souhaite utiliser (ici la version 2). Elle retourne la valeur 0 si tout s'est bien passé.
Puis à la fin, placez celui-ci :
Code : C
Cette fonction va simplement libérer les ressources allouées par la fonction WSAStartup().
Sur Linux
Sur Linux, c'est un peu différent puisque les fichiers à inclure ne sont pas les mêmes...
Pour combler l'écart entre Windows et Linux, nous utiliserons des
définitions et des
typedef.
Commençons par inclure les fichiers nécessaires :
Code : C1
2
3
4
5
6
7 | #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
|
Un premier problème se pose :
Dans le fichier
"socket.h" de Linux, la fonction qui sert à fermer une socket (que nous verrons par la suite) se nomme
close alors que dans le fichier
"winsock2.h" de Windows la fonction se nomme
closesocket ... Pour éviter de faire deux codes sources pour deux OS différents, nous utiliserons une définition comme il suit :
Code : C1 | #define closesocket(param) close(param)
|
Ainsi dans le code la fonction closesocket() sera remplacée par la fonction close() qui pourra ensuite être exécutée.
Le deuxième problème vient du fait qu'il "manque" deux définitions et trois
typedef qui peuvent nous être utile dans le fichier
"socket.h" de Linux par rapport au fichier
"winsock2.h" de Windows.
Voila donc le contenu de notre fichier pour le moment :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(param) close(param)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
|
Sachez qu'il y a beaucoup de fichiers à inclure par rapport à Windows mais qu'ils sont tous utiles.
Un code portable
Pour pouvoir avoir un code un peu plus portable, nous utiliserons les définitions WIN32 et linux.
Cette méthode indiquera à votre compilateur le code à compiler en fonction de votre OS.
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 | //Si nous sommes sous Windows
#if defined (WIN32)
#include <winsock2.h>
// Sinon, si nous sommes sous Linux
#elif defined (linux)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
// Define, qui nous serviront par la suite
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close (s)
// De même
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#endif
// On inclut les fichiers standards
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// Si la plateforme est Windows
#if defined (WIN32)
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);
#endif
// ICI on mettra notre code sur les sockets
// Si la plateforme est Windows
#if defined (WIN32)
WSACleanup();
#endif
return EXIT_SUCCESS;
}
|