Aller au menu - Aller au contenu

Icône Histoire et fonctionnement

Avatar
Mise à jour : 05/05/2009
Difficulté : Facile Facile
3 369 visites depuis 7 jours, dont 294 sur ce chapitre classé 48/786
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.
Sommaire du chapitre :
Icône du chapitre
Sommaire Chapitre suivant

Un peu d'histoire

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 0 à 216-1 inclus (soit 65535 :p ). Chacun de ces ports est associé à une application (à savoir que les 1024 premiers ports sont réservé à des utilisations bien précises).
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 :p ?

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 :p ).
Le principal atout des sockets est que les informations sont transmises directement au programme voulu en plus d'être plus sécurisé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 XHTML, votre navigateur va utiliser les sockets pour demander au serveur le code source de la page, pour pouvoir afficher ce qu'elle contient :

Image utilisateur


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 :p .

Leurs fonctionnement

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 :p .


Les inclusions et les ressources



Sur Windows


Tout d'abord, n'oubliez pas, dans chaque projet que vous créez, d'ajouter le fichier "ws2_32.lib" (pour le compilateur Visual C++) ou "libws2_32.a" (pour les autres) 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 :p .

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 de Windows, 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
1
#include <winsock2.h>


En général, vous aurez besoin des fichiers standards "stdio.h" et "stdlib.h".
Nous allons donc aussi les inclure :

Code : C
1
2
3
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>


On peut remarquer que le type socklen_t qui existe sous Linux, n'est pas défini sous Windows. Ce type sert à stocker la taille d'une structures de type sockaddr_in. Ça n'est rien d'autre qu'un entier mais il nous évitera des problèmes éventuels de compilation sous Linux par la suite. Il va donc falloir le définir nous même à l'aide du mot clef typedef comme il suit :

Code : C
1
typedef int socklen_t;


De plus, vous devrez ajouter, dans le début de votre fonction main, le code suivant pour pouvoir utiliser les sockets sous Windows :

Code : C
1
2
WSADATA WSAData;
WSAStartup(MAKEWORD(2,2), &WSAData);

La fonction WSAStartup sert à initialiser la bibliothèque WinSock. La macro MAKEWORD transforme les deux entiers (d'un octet) qui lui sont passés en paramètres en un seul entier (de 2 octets) qu'elle retourne. Cet entier sert à renseigner la bibliothèque sur la version que l'utilisateur souhaite utiliser (ici la version 2,0). Elle retourne la valeur 0 si tout s'est bien passé.
Puis à la fin, placez celui-ci :

Code : C
1
WSACleanup();

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 : C
1
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 : C
1
#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
48
49
50
51
52
//Si nous sommes sous Windows
#if defined (WIN32)

    #include <winsock2.h>

    // typedef, qui nous serviront par la suite
    typedef int socklen_t;

// 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,2), &WSAData);
    #endif

    // ICI on mettra notre code sur les sockets

    // Si la plateforme est Windows
    #if defined (WIN32)
        WSACleanup();
    #endif

    return EXIT_SUCCESS;
}

Q.C.M.

Dans quelle situation pouvons-nous avoir besoin des sockets ?
De quel système les sockets proviennent-il ?
Qu'est ce qu'un port ?

Statistiques de réponses au QCM

Sommaire Chapitre suivant

Partager

25 commentaires pour "Histoire et fonctionnement"
Note moyenne : 3.54 / 4 (79 votes)
Pseudo Commentaire
Hors ligne heero78 # Posté le 01/01/2009 à 19:57:15
Clique sur mon avatar. ;)
Avatar

Études : Université de Bordeaux

Merci pour ce tutoriel, c'est sympa pour débuter. :)

Citation : onunload='open('');'
EDIT: Sur le site de Microsoft il dise pour le premier paramètre de la fonction
WSAStartup():

The highest version of Windows Sockets specification that the caller can use. The high-order byte specifies the minor version number; the low-order byte specifies the major version number.

Ca renseigne bien sur le numéro de version non???

Le premier paramètre est bien un WORD destiné à renseigner sur le numéro de la version que l'on peut utiliser.
Pour créer ce WORD on utilise la macro MAKEWORD(a, b), mais contrairement a :
Citation : zephyr111
La macro MAKEWORD renseigne la bibliothèque sur la version que l'utilisateur souhaite utiliser

cette macro ne sert pas a renseigner quoi que ce sois. je plussois donc la remarque de -ed-.

Pour exemple chez moi :
Code : C
1
2
3
4
5
6
7
/* winsock2.h */
typedef WSADATA *LPWSADATA;
int PASCAL WSAStartup(WORD,LPWSADATA);
/* windef.h */
typedef unsigned short WORD;
typedef unsigned char BYTE;
#define MAKEWORD(a,b)  ((WORD)(((BYTE)(a))|(((WORD)((BYTE)(b)))<<8)))

En esperant que ça puisse éclaircir les idées de certain. :)

Citation : -ed-
Citation : Pas de titre
Les ports sont des numéros allant de 1 à 216 (soit 65536 :p ).

Pour être tout à fait précis, il y a 216 ports numérotés de 0 à 65535. A corriger aussi dans le QCM.

a la question "Qu'est ce qu'un port ? ", la réponse 2 (C’est un endroit permettant d'abriter les navires) est correcte aussi. :p
 
Hors ligne Kaleidoscopique # Posté le 25/01/2010 à 17:11:06
Kaleidoscopiquement votre.
Avatar

Avis : Décevant
Flux RSS

Études : Université de Lyon

Hello !

Pour ceux qui ont des soucis avec Dev-cpp sous Windows c'est normal, le tuto oublie une partie importante.
Les étapes pour pouvoir compiler votre projet sous Dev-cpp :

  • Créer un projet (et pas juste "un fichier source") en C
  • Mettre votre code dans le fichier main.c
  • Faites un clic droit sur votre projet dans l'arborescence de gauche
  • Sélectionnez "Options du projet"
  • Onglet "Paramètres"
  • Cliquez sur "Ajouter fichier"
  • Sélectionnez C:/Dev-Cpp/lib/libwsock32.a (cf : http://screencast.com/t/Y2ZmN2JiYTgt)


Et COMPILEZ :)
Sinon, ce tuto est une mine d'or, merci à toi !
Hors ligne santakill # Posté le 27/03/2010 à 12:26:14

Pour ceux qui ont encore des problèmes de compilation avec Mingw GCC à cause d'une erreur du style :

WSAStartup() undefined

Voici une solution :

Soit toto.c votre fichier source à compiler.
faite l'inclusion de winsock2
fait ensuite un gcc toto.c -lws2_32.

Ne pas mettre -lws2_32 avant toto.c : gcc -lws2_32 toto.c, sinon ça ne marche pas (en tout cas chez moi)

Pour informations, si l'on désire ajouter une librairie (*.lib), il faut procéder de la sorte:
Soit toto.c le source à compiler et tutu.lib la librairie à linker.
Faites alors un : gcc toto.c -ltutu

Pour ce qui est de la directive #pragma(lib,...), j'ai vu que celle ci était réservée à certains compilateur mais pas à GCC
Hors ligne sebbu # Posté le 30/04/2010 à 16:09:32

Études : Université de Dijon

Citation : Zimm i48
En plus (et sans être le but principal du tuto, tu viens de me donner le code préprocesseur pour faire du code portable, dont je connaissais l'existence mais que je n'arrivais pas à trouver sur internet :) ).

Un cadeau dont j'espère que tu appréciera : Pre-defined C/C++ Compiler Macros

Sinon, moi je me suis fait une mini-librairie où j'ai regroupé les fonctions réseaux et géré la portabilité, pour ne pas avoir à m'en soucier dans mes différents code.

PS : cette librarie est fortement inspiré de psock.h / psock.c trouvable sur Open Source Code Search Engine, et est en cours de réécriture vers une belle classe C++ (toujours en librarie dynamique)

Image utilisateur
 
Hors ligne Tomn # Posté le 28/11/2011 à 18:47:26
Avatar

Pour que le code fonctionne sur Mac,
il faudrait remplacer le :
Code : C
1
#elif defined (linux)

en
Code : C
1
#else

Tout simplement.
Ou comme l'a dit blargzieg :
Code : C
1
#elif defined (linux) || defined (__APPLE__)

C/C++ • (x)HTML • CSS • PHP/SQL • JavaScript • Objective-C • Infographie 2D/3D • …
 

Voir tous les commentaires