Sockets File - Plateforme e-learning Moodle de l`INSA de Rouen

Transcription

Sockets File - Plateforme e-learning Moodle de l`INSA de Rouen
Informatique Répartie
Les Sockets
Alexandre Pauchet
BO.B.RC.18 – [email protected]
Introduction
Définition



Un socket est un port de communication ouvert
permettant de faire passer des flux
C'est une interface entre la couche transport et les
couches applicatives du modèle OSI
La communication est

en point à point en mode client-serveur,

bi-directionnelle,

en mode connecté (TCP) ou non connecté (UDP)
3
Communication point à point bidirectionnelle
●
Un socket désigne l'extrémité d'une connexion
●
Un socket est associé à un port
●
La connexion établie, la communication est
similaire à une écriture de fichier
(Tiré de [1])
4
Modes de connexion
(Tiré de [1])
Mode connecté (TCP) : une liaison préalable aux données est établie
●
Mode non connecté (UDP) : aucune liaison initiale n'est établie,
chaque message est envoyé individuellement
●
5
Comparaison modes connecté / non connecté

Avantages du mode non connecté :



Pas de connexion à établir entre le client et le serveur
Rapide
Avantages du mode connecté :


Fiable
Séquencement des messages
6
Sockets en C
Création d’un socket en C

Les librairies :
#include <sys/types.h>
#include <sys/socket.h>

Création d’un socket :
int socket(int domain,
int type,
Retourne -1
si erreur
int protocol)
Familles de Sockets :
- local : PF_LOCAL
- internet : PF_INET
Types de communication :
- connecté : SOCK_STREAM
- non connecté : SOCK_DGRAM
Protocoles :
- TCP : IPPROTO_TCP
- UDP : IPPROTO_UDP
- local : 0
8
Création d’un socket en C

Table des correspondances :
Domain
PF_LOCAL
PF_LOCAL
PF_INET
PF_INET

Socket Type
SOCK_STREAM
SOCK_DGRAM
SOCK_STREAM
SOCK_DGRAM
Protocol
0
0
IPPROTO_TCP
IPPROTO_UDP
Description
Socket local avec connexion
Socket local sans connexion
Socket internet basé sur TCP
Socket Internet basé sur UDP
Exemples :
int s1, s2;
s1 = socket(PF_LOCAL, SOCK_DGRAM, 0);
s2 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
9
Lier un socket à une adresse et à un port


Indispensable côté serveur, facultatif côté client
Spécification de l'adresse :
int bind(int socketid,
l’identifiant de socket
valeur retournée par socket()
Retourne -1 si erreur
struct sockaddr *addr,
int addrlen)
adresse locale
(EndPoint)
longueur en octets
de l ’adresse
10
La structure d’adresse

Chaque protocole a son format d’adresse, mais
struct sockaddr est générique :
struct sockaddr {
u_short sa_family;
char sa_data[14];
}

AF_LOCAL,
AF_INET, etc.
l’adresse proprement dite
Dans la pratique on utilise des variables dont le
type correspond au protocole qu’on utilise, par
exemple : struct sockaddr_in (AF_INET)
11
La structure d’adresse

Les deux structures d’adresse les plus utilisées :

Unix (défini dans sys/un.h):
struct sockaddr_un {
sa_family_t sun_family;
char
sun_path[108];
}

AF_LOCAL ou AF_UNIX
Chemin
Internet (défini dans netinet/in.h):
Port
(conversion
nécessaire !)
inutilisé !!
struct sockaddr_in {
sa_family_t sin_family;
unit16_t
sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
}
AF_INET
Adresse IP
struct in_addr { uint32_t s_addr }
12
La structure d’adresse
Exemple :
struct sockaddr_in
adresse.sin_family
inet_pton(AF_INET,
// inet_addr()
adresse.sin_port =
adresse;
= AF_INET;
"172.29.2.43", &(adresse.sin_addr));
est deprecated...
htons(9090); // Integer -> uint16_t
Fonctions de conversion / constantes utiles
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(adresse.sin_addr), ip, INET_ADDRSTRLEN);
adr_serveur.sin_addr.s_addr = htonl(INADDR_ANY);
// Pour utiliser n'importe quelle adresse locale
Remarque : fonctions dédiées aux IPv4
13
Sockets en C
mode non connecté
Fonctionnement de base
Serveur
socket()
bind()
recvfrom()
bloquant
Client
socket()
bind()
sendto()
recvfrom()
sendto()
close()
bloquant
close()
15
Réception d'un message
Retourne -1
si erreur
Le socket
int recvfrom( int s,
Le buffer
pour stocker
le message
void *buf,
0 dans 99%
des cas
unsigned flags,
Adresse de
l'émetteur
const struct sockaddr *from
longueur maximale
de l’adresse
int len,
Le taille maximale
du buffer
int *fromlen);
16
Envoi d'un message
Retourne -1
si erreur
int sendto(
Le message
Le socket
int s,
const void *msg,
int len,
Longueur du message en octets
0 dans 99%
des cas
unsigned flags,
Adresse du
destinataire
const struct sockaddr *to
Longueur de l’adresse
int tolen);
17
Exemple de serveur
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<unistd.h>
<stdlib.h>
<errno.h>
<string.h>
<time.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>
static void erreur(const char *message) {
fputs(strerror(errno), stderr);
fputs(": ", stderr);
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc,char **argv) {
char *IPServeur=NULL, nom[512], message[512],
ipClient[INET_ADDRSTRLEN];
int portServeur, socketServeur, longueur,
nbOctets;
struct sockaddr_in adresseServeur,
adresseClient;
// Récupération des paramètres
if ( argc>=3 ) {
IPServeur = argv[1];
portServeur = atoi(argv[2]);
}else if( argc>=2 ){
IPServeur = "127.0.0.1";
}else {
IPServeur = "127.0.0.1";
portServeur = 1024;
}
// Construction de l'adresse
memset(&adresseServeur, 0,
sizeof(adresseServeur));
adresseServeur.sin_family = AF_INET;
adresseServeur.sin_port = htons(portServeur);
inet_pton(AF_INET, IPServeur,
&(adresseServeur.sin_addr));
if(adresseServeur.sin_addr.s_addr==INADDR_NONE)
erreur("mauvaise addresse");
// Création du Socket
socketServeur = socket(PF_INET, SOCK_DGRAM,
IPPROTO_UDP);
if( socketServeur==-1 )
erreur("socket");
18
Exemple de serveur
// Bind
if( bind(socketServeur, (struct sockaddr *)&adresseServeur, sizeof(adresseServeur))==-1 )
erreur("bind()");
// Ecouter le Socket et traiter les requêtes
longueur = sizeof(adresseClient);
nbOctets = recvfrom(socketServeur, nom, sizeof(nom), 0, (struct sockaddr *)&adresseClient,
&longueur);
if(nbOctets==-1) {
erreur("rcvfrom()");
}else {
nom[nbOctets]='\0';
inet_ntop(AF_INET, &(adresseClient.sin_addr), ipClient, INET_ADDRSTRLEN);
printf("(%s:%u) : '%s'\n", ipClient, (unsigned)ntohs(adresseClient.sin_port), nom);
strcpy(message, "Hello ");
strcat(message, nom);
strcat(message, " !");
if( sendto(socketServeur, message, strlen(message), 0, (struct sockaddr *)&adresseClient,
longueur)==-1 )
erreur("sendto()");
}
close(socketServeur);
return 1;
}
19
Exemple de client
// Envoi du nom
strcpy(nom, argv[3]);
// 3eme argument : nom
envoye = sendto(s, nom, strlen(nom), 0 ,
(struct sockaddr *)&adr_serveur,
sizeof(adr_serveur));
if( envoye < 0 )
erreur("sendto()");
int main(int argc,char **argv) {
int s, sb, envoye, recu, l;
struct sockaddr_in adr_serveur,
struct sockaddr_in adr_client, adr;
char nom[512], message[512],
char ip[INET_ADDRSTRLEN];
// Création de l'adresse
adr_serveur.sin_family = AF_INET;
inet_pton(AF_INET, argv[1],
&(adr_serveur.sin_addr));
// 1er argument : IP du serveur
adr_serveur.sin_port =
htons(atoi(argv[2]));
// 2nd argument : port du serveur
// Réception de la réponse
l = sizeof(adr);
recu = recvfrom(s, message, sizeof(message),
0, (struct sockaddr *)&adr, &l);
if( recu < 0 )
erreur("recvfrom()");
message[recu] = 0;
inet_ntop(AF_INET, &(adr.sin_addr), ip,
INET_ADDRSTRLEN);
printf("Message recu (par %s:%u) : '%s'\n",
ip,(unsigned)ntohs(adr.sin_port), message);
if(adr_serveur.sin_addr.s_addr==INADDR_NONE)
erreur("mauvaise addresse");
// Création du Socket
s = socket(PF_INET, SOCK_DGRAM,
IPPROTO_UDP);
if ( s == -1 ) erreur("socket()");
close(s);
putchar('\n');
return 0;
}
20
Sockets en C
mode connecté
Fonctionnement de base
Serveur
Client
socket()
bind()
listen()
socket()
bind()
accept()
bloquant
connect()
read() / write()
read() / write()
close()
close()
22
Les fonctions listen() et accept()
int listen( int socketid,
int backlog)
Identifiant de socket
Longueur maximale
de la file d ’attente
0 si Ok
-1 sinon
int accept( int socketid,
struct sockaddr* addr,
int* addrlen)
0 si Ok
-1 sinon
Longueur de
l’adresse
Identifiant de socket
Adresse du
client
23
La connextion
int connect( int socketid,
Identifiant de socket
valeur retournée par socket()
Retourne -1 si erreur
struct sockaddr *addr,
adresse du
serveur
int addrlen)
longueur en octets
de l ’adresse
24
Exemple de serveur
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<unistd.h>
<stdlib.h>
<errno.h>
<string.h>
<time.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>
// Récupération des paramètres
if ( argc>=3 ) {
IPServeur = argv[1];
portServeur = atoi(argv[2]);
}else if( argc>=2 ){
IPServeur = "127.0.0.1";
}else {
IPServeur = "127.0.0.1";
portServeur = 1024;
}
static void erreur(const char *message) {
fputs(strerror(errno), stderr);
fputs(": ", stderr);
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
// Construction de l'adresse
memset(&adresseServeur, 0,
sizeof(adresseServeur));
adresseServeur.sin_family = AF_INET;
adresseServeur.sin_port = htons(portServeur);
inet_pton(AF_INET, IPServeur,
&(adresseServeur.sin_addr));
int main(int argc,char **argv) {
char *IPServeur=NULL, nom[512], message[512],
ipClient[INET_ADDRSTRLEN];
int portServeur, socketServeur, longueur,
socketClient, recu;
struct sockaddr_in adresseServeur,
adresseClient;
if(adresseServeur.sin_addr.s_addr==INADDR_NONE)
erreur("mauvaise addresse");
// Création du Socket
socketServeur = socket(PF_INET, SOCK_STREAM,
IPPROTO_TCP);
if( socketServeur==-1 )
erreur("socket");
25
Exemple de serveur
// Bind
if( bind(socketServeur, (struct sockaddr *)&adresseServeur, sizeof(adresseServeur))==-1 )
erreur("bind()");
// Ecoute du Socket
if( listen(socketServeur, 10)==-1)
erreur("listen()");
// Traitement de la requête
longueur = sizeof(adresseClient);
socketClient = accept(socketServeur, (struct sockaddr *)&adresseClient, &longueur);
if(socketClient==-1) {
erreur("accept()");
}else {
recu = read(socketClient, &nom, sizeof(nom)-1);
if( recu==-1)
erreur("read()");
nom[recu-1]='\0';
inet_ntop(AF_INET, &(adresseClient.sin_addr), ipClient, INET_ADDRSTRLEN);
printf("(%s:%u) : '%s'\n", ipClient, (unsigned)ntohs(adresseClient.sin_port), nom);
strcpy(message, "Salut ");
strcat(message, nom);
strcat(message, " !\n");
if( write(socketClient, message, strlen(message))==-1 )
erreur("write()");
}
close(socketClient);
close(socketServeur);
return 1;
}
26
Exemple de client
// Connection
SocketServeur = connect(socketClient,
(struct sockaddr *)&adr_serveur,
sizeof(adr_serveur));
if( socketServeur==-1 )
erreur("connect()");
int main(int argc,char **argv) {
int socketClient, socketServeur, recu;
struct sockaddr_in adr_serveur, adr_client,
adr;
char nom[512], message[512],
ip[INET_ADDRSTRLEN];
// Envoi de la requête
strcpy(nom, argv[3]); // 3eme argument : nom
strcat(nom, "\n");
if( write(socketClient, nom, strlen(nom))==-1 )
erreur("write()");
// Création de l'adresse
adr_serveur.sin_family = AF_INET;
inet_pton(AF_INET, argv[1],
&(adr_serveur.sin_addr));
// 1er argument : IP du serveur
adr_serveur.sin_port = htons(atoi(argv[2]));
// 2nd argument : port du serveur
if(adr_serveur.sin_addr.s_addr==INADDR_NONE)
erreur("mauvaise addresse");
// Réception de la réponse
recu = read(socketClient, &message,
sizeof(message)-1);
if( recu==-1 )
erreur("read()");
message[recu-1] = '\0';
// Création du Socket
socketClient = socket(PF_INET, SOCK_STREAM,
IPPROTO_TCP);
if ( socketClient == -1 )
erreur("socket()");
inet_ntop(AF_INET, &(adr.sin_addr), ip,
INET_ADDRSTRLEN);
printf("(%s:%u) : '%s'\n", ip,
(unsigned)ntohs(adr.sin_port), message);
close(socketServeur);
close(socketClient);
return 0;
}
27
Sockets en Java
Le package java.net
java.lang.Object
java.net
InetAddress
Inet4Address
Inet6Address
SocketAddress
DatagramPacket
DatagramSocket
InetSocketAddress
Socket
ServerSocket
29
Classe InetAdress
●
Représente les adresses IP
●
Encapsule l'accès au serveur de noms DNS
●
Pas de création d'instance mais :
public static InetAddress getLocalHost() throws UnknownHostException
public static InetAddress getByName(String host) throws UnknownHostException
public static InetAddress[] getAllByName(String host) throws UnknownHostException
30
Classe Socket
●
●
Sockets de flux (client et serveur)
Méthodes de base :
public Socket(String host, int port) throws UnknownHostException, IOException
public Socket(InetAddress address, int port) throws IOException
public InetAddress getInetAddress() // adresse IP distante
public InetAddress getLocalAddress() // adresse IP locale
public int getPort() // port distant
public int getLocalPort() // port local
public InputStream getInputStream() throws IOException
public OutputStream getOutputStream() throws IOException
void close()
31
Sockets en Java
mode non connecté
32
Classe DatagramSocket
●
Communication en mode non connecté
●
Client/serveur via une interface par socket
●
Méthodes de base :
public DatagramSocket() throws SocketException
public DatagramSocket(int port) throws SocketException
public DatagramSocket(int port, InetAddress addr) throws SocketException
void close()
InetAddress getInetAddress()
int getPort()
InetAddress getLocalAddress()
int getLocalPort()
public void send(DatagramPacket p) throws IOException
public void receive(DatagramPacket p) throws IOException
33
Classe DatagramPacket
●
Méthodes de base :
DatagramPacket(byte[] buf, int length)
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
InetAddress getAddress()
byte[] getData()
int getLength()
int getPort()
void setAddress(InetAddress iaddr)
void setData(byte[] buf)
void setLength(int length)
void setPort(int iport)
34
Fonctionnement de base
Serveur
Client
s = new DatagramSocket(...)
s = new DatagramSocket(...)
r = new DatagramPacket(...)
e = new DatagramPacket(...)
r = new DatagramPacket(...)
s.receive(r)
bloquant
e = new DatagramPacket(...)
s.send(e)
s.receive(r)
s.send(e)
bloquant
s.close()
s.close()
35
Exemple de serveur
import java.io.*;
import java.util.*;
import java.net.*;
// Réponse
adresseClient = reception.getAddress();
portClient = reception.getPort();
nom = new String(reception.getData(), 0,
reception.getLength());
System.out.println("Message de (" +
adresseClient + ":" + portClient
+ ") => " + nom);
message = "Salut " + nom + " !";
reponse = message.getBytes();
envoi = new DatagramPacket(reponse,
reponse.length,
adresseClient,
portClient);
socket.send(envoi);
public class Serveur {
public static void main(String[] args) throws
Exception {
InetAddress adresseClient;
int portClient;
DatagramSocket socket;
byte[] requete = new byte[100], reponse;
DatagramPacket reception, envoi;
String nom, message;
if(args.length != 2) {
System.out.println("2 arguments : IP
Port)");
}
else {
// Création du Socket
socket = new
DatagramSocket(Integer.parseInt(args[1]),
InetAddress.getByName(args[0]));
//Fermeture du Socket
socket.close();
}
}
}
// Création du DatagramPacket
// et réception d'une requête
reception = new DatagramPacket(requete,
requete.length);
socket.receive(reception);
36
Exemple de client
import java.io.*;
import java.util.*;
import java.net.*;
public
class Client {
public static void main(String[] args) throws Exception {
InetAddress adresse = InetAddress.getByName(args[0]);
int portUDP = Integer.parseInt(args[1]);
byte[] requete = args[2].getBytes(), reponse = new byte[100], test;
// Création du Socket
DatagramSocket socket = new DatagramSocket();
// Création des DatagramPacket d'envoi et de réception
DatagramPacket envoi = new DatagramPacket(requete, requete.length, adresse, portUDP),
reception = new DatagramPacket(reponse, reponse.length);
// Requête : envoi puis réception
socket.send(envoi);
socket.receive(reception);
String texte = new String(reception.getData(), 0, reception.getLength());
System.out.println(texte);
// Fermeture du Socket
socket.close();
}
}
37
Sockets en Java
mode connecté
38
Classe ServerSocket
●
Communication en mode connecté
●
Client/serveur via une interface par socket
●
Constructeur :
public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException
●
Acceptation d'une connexion client (bloquant)
public Socket accept() throws IOException
39
Fonctionnement de base
Serveur
Client
se = new ServerSocket(...)
sc = se.accept()
bloquant
s = new Socket(...)
is = sc.getInputStream()
os = sc.getOutputStream()
is = s.getInputStream()
os = s.getOutputStream()
lectures/écriture
lectures/écriture
s.close()
s.close()
40
Exemple de serveur
import java.io.*;
import java.util.*;
import java.net.*;
// Lecture d'une requête
socketInputStream =
new BufferedReader(
new InputStreamReader(
socketClient.getInputStream()));
nom = socketInputStream.readLine();
System.out.println("Message de (" +
socketClient.getInetAddress()
+ ":"
+ socketClient.getPort()
+ ") => " + nom);
public class Serveur {
public static void main(String[] args) throws
Exception {
ServerSocket socketEcoute;
Socket socketClient;
PrintStream socketOutputStream;
BufferedReader socketInputStream;
String nom;
if(args.length != 2) {
System.out.println("2 arguments : IP
Port)");
}
else {
// Création du Socket et mise en attente
socketEcoute = new
ServerSocket(Integer.parseInt(args[1]),
10,
InetAddress.getByName(args[0]));
socketClient = socketEcoute.accept();
// Écriture de la réponse
socketOutputStream =
new PrintStream(
socketClient.getOutputStream());
socketOutputStream.print("Salut " + nom
+ " !\n");
// Fermeture des Sockets
socketClient.close();
socketEcoute.close();
}
}
}
41
Exemple de client
import java.io.*;
import java.util.*;
import java.net.*;
public
class Client {
public static void main(String[] args) throws Exception {
Socket s;
PrintStream socketOutputStream;
BufferedReader socketInputStream;
int erreur;
if(args.length != 3) {
System.out.println("4 arguments : IP Port Nom)");
} else {
// Création du Socket
s = new Socket(args[0], Integer.parseInt(args[1]));
// Écriture de la requête
socketOutputStream = new PrintStream(s.getOutputStream());
socketOutputStream.print(args[2] + "\n");
// Récupération de la réponse
socketInputStream = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(socketInputStream.readLine());
// Fermeture du Socket
s.close();
}
}
}
42
Références
●
[1]
http://deptinfo.unice.fr/~dalle/wiki/uploads/Enseigne
ments/7-SYS-L2.pdf
43

Documents pareils