Cette section va essayer de vous expliquer ce qu'est une socket, son implémentation dans Windows. Les socket sont utilisées dans tout les système leur manipulation est quelque peu différente, mais le point commun entre ces systèmes est lié à leur utilisation et aux protocoles référencés par les [b]RFC[/b]





Une socket défini l'interface entre le système d'exploitation et les logiciels. Un logiciel qui est amenée à utiliser une socket aura accès à un type de réseau. La programmation réseau se fait donc via des socket, ensuite selon le type de réseau à atteindre, le paramètrage de la socket intervient. L'appel à une socket se fait généralement par inclusion d'une bibliothèque de fonctions.


Ordinateur -> Système d'exploitation -> Langage de programmation     -> Socket   -> Logiciel
   Windows -> Langage C              -> #include <winsock.h>  [...]  -> Logiciel 




Passons à la pratique. Le programme source du serveur est celui-ci, vous pourrez remarquer la boucle infinie while(1) qui montre bien que le serveur est en écoute et donc en attente d'un client.


#include <time.h>     // time, ctime
#include <stdio.h>    // printf
#include <conio.h>    // clrscr
#include <winsock2.h> // accès aux sockets
 
// Pour Visual C++
#pragma comment(lib, "ws2_32.lib")
 
void main()
{
  char buffer [255] ;
  time_t t;
 
 
  WSADATA WSAData;
  WSAStartup(MAKEWORD(2,0), &WSAData);
 
  SOCKET sock;      // Déclataration des sockets
  SOCKET csock;     //
  SOCKADDR_IN sin;  // Déclaration des structures d'adressage (IP, Port, ...)
  SOCKADDR_IN csin; //
 
   /****
    * La création d'un socket se fait gr&acirc;ce à la fonction
    * socket() :
    *
    * int socket(FAMILLE,TYPE,PROTOCOLE)
    *
    * FAMILLE représente la famille de protocole utilisé (AF_INET pour TCP/IP
    * utilisant une adresse Internet sur 4 octets : l'adresse IP ainsi qu'un
    * numéro de port afin de pouvoir avoir utiliser plusieurs sockets sur une m&ecirc;me
    * machine, AF_UNIX pour les communications UNIX en local sur une m&ecirc;me
    * machine, notamment pour les communications avec le serveur X)
    * TYPE indique le type de service (orienté connexion ou non : TCP ou UDP).
    * Dans le cas d'un service orienté connexion (c'est généralement le cas),
    * l'argument TYPE doit prendre la valeur SOCK_STREAM (communication par
    * flot de données). Dans le cas contraire (protocole UDP) le paramètre
    * TYPE doit alors valoir SOCK_DGRAM (utilisation de datagrammes,
    * blocs de données) protocole permettant de fournir le service désiré.
    * PROTOCOLE : Dans le cas de la suite TCP/IP il n'est pas
    * utile, on le mettra ainsi toujours à 0 La fonction socket() renvoie un
    * entier - un handle - qui correspond à un descripteur du socket nouvellement
    * créé et qui sera passé en paramètre aux fonctions suivantes.
    * En cas d'erreur, la fonction socket() retourne -1.
    *
   /***/
  sock = socket(AF_INET, SOCK_STREAM, 0);
   /***/
 
  sin.sin_addr.s_addr = INADDR_ANY;
  sin.sin_family      = AF_INET;
  sin.sin_port      = htons(4444);
 
   /***
    * Après création du socket, il faut le lier à un point de communication
    * défini par une adresse et un port, c'est le r&ocirc;le de la fonction bind()
    * Dans ce cas, on BIND l'adresse locale (0.0.0.0) accessible depuis l'extérieur
   /***/
  bind(sock, (SOCKADDR *)&sin, sizeof(sin));
   /***/
  listen(sock, 0);
 
   clrscr();
   printf("/nServer running.../n/n");
 
  while(1)    // On se met en écoute, tant que 1 est différent de 0...
  {
    int sinsize = sizeof(csin); // on récupère la taille de l'adresse
 
    if((csock = accept(sock, (SOCKADDR *)&csin, &sinsize)) != INVALID_SOCKET)
    // si la fonction 'accept' ne retourne pas la valeur INVALID_SOCKET
    // on affiche un message de bienvenue
    {
      memset(buffer,0,255);
 
      wsprintf(buffer,"welcome");   // on copie "welcome" dans buffer
      send(csock,buffer,255,0);     // on envoie buffer au client via
                                    // la socket 'csock'
 
      time(&t);                     // on récupère le temps local
 
      // Du c&ocirc;té du serveur on affiche l'adresse IP du client et l'heure locale
      printf("new client connected: %s  -  time: %s",
         inet_ntoa(csin.sin_addr),ctime(&t));
    }
  }
} 




Pour utiliser les socket en langage C, sous Windows, il faut inclure le ficheir de bibliothèque winsock2.h, winsock.h inclus eux-même dans windows.h. C'est grâce à ces entêtes que l'on peut créer et manipuler les sockets car les fonctions à utiliser se trouvent dedans. Nous allons voir comment coder le client du serveur ci-dessus. La source est suffisament commentée.


#include <string.h>   // strlen
#include <stdio.h>    // printf, memset
#include <conio.h>    // getch()
#include <winsock2.h> // connect, WSA, SOCKET
#pragma comment(lib, "ws2_32.lib")
 
void main()
{
char strIP [15] ;   // variable qui va accueillir l'adresse ip
                  // max. 15 caractères : 127.000.000.000 4x3+3=15
 
WSADATA WSAData;                      // Variable pour le support Winsock
WSAStartup(MAKEWORD(2,0), &WSAData);  // Initialisation du support Winsock
 
SOCKET sock;      // La socket - le support réseau - qui sera utilisé
                  // pour la réception et la connexion.
 
SOCKADDR_IN sin;  // Socket de paramètrage
 
char buffer [255] ;
unsigned int iPort=4444;
 
sock = socket(AF_INET, SOCK_STREAM, 0);
// on créé notre socket selon le modèle de flux "chaine de caractère"
 
 
printf("Adresse IP: "); // affichage de la demande de saisie de l'adresse ip du serveur
scanf("%s",strIP);      // on sauvegarde dans strIP l'adresse IP
 
printf("Port: ");       // de m&ecirc;me pour le numéro de port
scanf("%d",&iPort);     //
 
 
if(!iPort) iPort=4444;  // par défaut on met 4444, si le port est nul
 
 
 
clrscr();
printf("Connecting to %s...",strIP);    // mise en forme...
 
sin.sin_addr.s_addr = inet_addr(strIP); // on initiailise la socket
sin.sin_family    = AF_INET;            // de paramètrage avec
sin.sin_port    = htons(iPort);         // l'ip, le port et le type
 
/****
 * Voici la liste des type de protocol utilisable en C ( C++, C# )
 * il s'agit du type de transport de donnée, par exemple AF_INET est le plus
 * utilisé car c'est celui qui utilise TCP/IP, UDP et ICMP (ping) pour
 * transférer les données d'un client vers un ma?tre. Concernant les autres
 * protocoles je vous renvoie à leur RFC (références, terme utilisé dans le
 * monde des réseaux) pour y avoir plus de détails.
 *
 *
 *                   Valeur
 *   Constante       numérique        Brève description
 *   -----------     ----------       -----------------------------------
 *   AF_UNIX         1                local to host (pipes, portals)
 *   AF_INET         2                internetwork: UDP, TCP, etc.
 *   AF_IMPLINK      3                arpanet imp addresses
 *   AF_PUP          4                pup protocols: e.g. BSP
 *   AF_CHAOS        5                mit CHAOS protocols
 *   AF_NS           6                XEROX NS protocols
 *   AF_IPX          AF_NS            IPX protocols: IPX, SPX, etc.
 *   AF_ISO          7                ISO protocols
 *   AF_OSI          AF_ISO           OSI is ISO
 *   AF_ECMA         8                european computer manufacturers
 *   AF_DATAKIT      9                datakit protocols
 *   AF_CCITT        10               CCITT protocols, X.25 etc
 *   AF_SNA          11               IBM SNA
 *   AF_DECnet       12               DECnet
 *   AF_DLI          13               Direct data link interface
 *   AF_LAT          14               LAT
 *   AF_HYLINK       15               NSC Hyperchannel
 *   AF_APPLETALK    16               AppleTalk
 *   AF_NETBIOS      17               NetBios-style addresses
 *   AF_VOICEVIEW    18               VoiceView
 *   AF_FIREFOX      19               Protocols from Firefox
 *   AF_UNKNOWN1     20               Somebody is using this!
 *   AF_BAN          21               Banyan
 *   AF_ATM          22               Native ATM Services
 *   AF_INET6        23               Internetwork Version 6
/****/
 
 
connect(sock, (SOCKADDR *)&sin, sizeof(sin));
// On se connecte en utilisant la socket et ses adressages associé (SOCKADDR_IN)
// SOCKADDR_IN : SOCKet ADDRess INput
// La socket 'sock' est utilisée pour les transferts de données selon le
// protocol, alors que la socket 'sin' est utilisée pour les paramètres de
// connexion, c'est à dire, l'h&ocirc;te, le port.
 
 
printf("Ok/n/n");
// Si on est connecté c'est : "Ok"
 
 
memset(buffer,0,255);
// Initialisation de buffer à 0 dans ses 255 cases
 
 
recv(sock, buffer, sizeof(buffer), 0);
// Réception des données provenant du serveur via notre socket 'sock'
// Un client ne fait que de se connecter et recevoir.
 
 
if(strlen(buffer)>4)
// Il se peut parfois que Windows ou un programme utilise ce port
// notamment quelques parefeu et retourne une valeur non signifiante,
// on estimera que cette valeur a moins de 4 caractères elle ne vaut pas
// la peine d'&ecirc;tre affichée.
{
   printf("Message from Server:/n/n%s/n/n",buffer);
   // Affichage du buffer
 
   getch();
   // On attend une réaction de l'utilisateur
}
 
 
closesocket(sock);
// Fermeture de la socket 'sock'
 
 
WSACleanup();
// On réinitliase le support de communication de Windows
// WSA : Windows Socket Application
// WINSOCK : WINdows SOCKet
} 




En terme de sécurité il faut bien paramétrer son firewall afin qu'il ne laisse pas n'importe quel programme se connecter au réseau, car s'il n'est pas très difficile de faire un programme qui se connecte au réseau, pour un hacker il n'est pas difficile de faire un virus qui se connecte à notre insu aux réseaux. En terme de sécurité dans le programme à écrire il faut bien attention aux buffer overflow et également à tout type de débordement, que ce soit de la pile (stack) ou autre. Je ne ferais qu'un bref aperçu. Un bon principe de sécurité est de bloquer tout ce qui n'est pas connu, une politique restrictive de sécurité est toujours mieux même si elle se révèle contraignante à mettre en place sur un réseau personnel.


// Ce code n'est pas sécurisé, si la personne saisie une chaine de plus de 15 caractères
char buff [15] ;
scanf("%s",buff);
 
// Il y a pour ça plusieurs méthode pour sécuriser le code, en voici quelques unes des plus simples: 
char buff [15] ;
scanf("%15s",buff);
 
char *buff;
scanf("%s",buff); 




Ce tutorial se termine ici. Voici une liste de lien qui ne peuvent qu'être utile afin comprendre plus en détail les socket ainsi que les sources des programmes :
Source du serveur
Source du client

Ainsi que des liens pour apprendre à utiliser les sockets :

Windows Socket 2.0
Asynchronous Server Socket Example
Programmation Socket en C sous Windows
Winsock par _SebF
Windows Sockets




   =>   Écrit par : Nicolas, le 05 décembre 2007


 
Mots clés :  
  c 
  
  network 
    >   Articles connexes :

Comment gagner du temps sur Internet

Comment gagner du temps sur Internet



/tmp et /var/log en noexec sur macOS

/tmp et /var/log en noexec sur macOS



GitVuln

GitVuln


HTTP Server, tell me who you are ?


Discuter avec un serveur web *apparement* muet ? Voici comment faire...

7110369