Après avoir créé le socket, il va falloir indiquer le port sur lequel on écoutera l'arrivée des datagrammes des clients.
Pour cela, on utilisera la fonction bind en lui passant 3 paramètres :Il va donc falloir déclarer une variante de la structure sockaddr correspondant à AF_INET. Il s'agit du type struct sockaddr_in. On commencera par mettre à zéro le contenu de cette structure via la fonction bzero de string.h, puis on affectera, au premier champ nommé ici sin_family, la valeur AF_INET.
struct sockaddr_in adr_srv; bzero(&adr_srv, sizeof(adr_srv)); adr_srv.sin_family = AF_INET;
Il faut ensuite remplir, dans la structure, le champ sin_port avec le numéro de son port TCP sur laquelle le serveur écoute et éventuellement le champ sin_addr avec l'adresse IPv4. (On peut également laisser à zéro l'adresse IPv4 pour écouter sur toutes les interfaces.)
inet_aton("127.0.0.1", &adr_srv.sin_addr); adr_srv.sin_port = htons(7);
Ayant ainsi précisé l'adresse 127.0.0.1 et le port 7, il ne reste plus qu'à appeler la fonction bind.
bind(fd_srv, (struct sockaddr *) &adr_srv, sizeof(adr_srv));
Il faut ensuite attendre, dans une boucle while, l'arrivée d'un datagramme via la fonction recvfrom qui nécessite 6 paramètres :
La fonction retourne le nombre d'octets reçus dans le buffer.
struct sockaddr_in adr_cli; socklen_t adr_cli_len; adr_cli_len = sizeof(adr_cli); n = recvfrom(fd_srv, &buffer, sizeof(buffer), MSG_WAITALL, (struct sockaddr *) &adr_cli, &adr_cli_len);
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <netdb.h> #include <sys/socket.h> #include <string.h> // pour la fonction bzero #include <arpa/inet.h> // pour la fonction inet_addr int main() { int fd_srv; struct sockaddr_in adr_srv, adr_cli; socklen_t adr_cli_len; int err; int n; char buffer[1024]; fd_srv = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd_srv<0) { printf("Erreur de creation de la socket !\n"); exit(1); } bzero(&addr, sizeof(adr_srv)); addr.sin_family = AF_INET; err = inet_aton("127.0.0.1", &adr_srv.sin_addr); if (err == 0) { printf("Adresse IPv4 invalide !\n"); exit(1); } addr.sin_port = htons(8080); err = bind(fd_srv, (struct sockaddr *) &adr_srv, sizeof(adr_srv)); if (err != 0) { printf("Erreur d'accès au port serveur !\n"); exit(1); } while(1) { adr_cli_len = sizeof(adr_cli); n = recvfrom(fd_srv, &buffer, sizeof(buffer), MSG_WAITALL, (struct sockaddr *) &adr_cli, &adr_cli_len); printf("Message de taille %d octets reçu depuis %s:%d\n", n, inet_ntoa(adr_cli.sin_addr), ntohs(adr_cli.sin_port)); } return 0; }
Dans les langages comme PHP ou Python, il existe des bibliothèques faisant l'interface avec les fonctions systèmes.
Le code de l'exemple écrit en C devient en PHP :
$sock_srv = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($sock_srv== false) die("Erreur de creation de la socket !\n"); $err = socket_bind($sock_srv, '127.0.0.1', 8080); if ($err == false) die("Erreur d'accès au port serveur !\n"); echo "Serveur lancé !\n"; while (true) { $from = ''; $port = 0; socket_recvfrom($sock_srv, $buf, 1024, MSG_WAITALL, $from, $port); echo "message de taille ",strlen($buf)," octets reçu depuis ",$from,":",$port,"\n"; }
Le code de l'exemple écrit en C devient en Python :
import socket try: sock_srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock_srv.bind(('127.0.0.1', 8080)) except socket.error: print("Erreur de lancement du serveur !") exit() print("Serveur lancé !") while True : try : buffer, adresse = sock_srv.recvfrom(1024) ip, port = adresse print("message de taille",len(buffer),"octets reçu depuis",ip+":"+str(port)) except socket.error : print("Erreur sur la lecture d'un datagramme !") exit()