Questions sur les comm client/serveur

mathieu -  
 sebsauvage -
Bonjour, voici mes questions (indépendantes):

- j'ai cru comprendre que pour établir une connexion client/serveur, le client commence par exécuter un appel socket() puis directement connect(). Mais alors comment le serveur peut il savoir comment envoyer la réponse au client (à quelle IP+port) ?

- Quelle est la différence entre listen et accept?

- Quand on écrit un programme serveur, quelle instruction permet de savoir qu'une connection a été demandée par un client? Est-ce que la fonction accept() est bloquante pour le prog jusqu'à ce qu'une connexion arrive ou est-ce que ça marche autrement?
Même chose pour un client: quand il envoie un connect(), est-ce que cette fonction est bloquante jusqu'à la réponse du serveur?

-n'importe quel client (browser, ftp, telnet ...) reçoit ses réponses sur un port. Or, j'utilise un système Linux et mes règles ipchains interdisent tous les paquets entrants. Comment se fait il que je puisse utiliser un browser, un client ftp ou n'importe quoi?

Je suis conscient que ça fait beaucoup de questions. Donc si quelqu'un connait juste l'adresse d'un site qui propose un tutorial sur les communications par socket (un peu plus détaillé que celui-ci), ça m'intéresse aussi.
A voir également:

5 réponses

sebsauvage
 
#### Question 1:
Le serveur effectue un listen() sur un port : cela 'ouvre' le port sur la machine, et attend des connexions.
Le(s) client(s) effectue(nt) un connect() sur le serveur.
Le server a un port fixe.
Les clients ont des ports variables.
A chaque connexion TCP sur le serveur, un socket est créé.
Exemple: si 2 clients (192.168.0.5 et 192.168.0.7) se connectent sur le même serveur (192.168.0.1) sur le port 80, cela créé 2 sockets:

(192.168.0.5:1057, 192.168.0.1:80)
(192.168.0.5:1245, 192.168.0.1:80)

Chaque socket TCP est une sorte de tuyau bidirectionnel dans lequel le serveur et le client peuvent échanger des données.
(Pour être précis: le serveur et le client peuvent simultanément envoyer des données à l'autre).

Le serveur peut sans problème distinguer ses 2 clients car il a 2 sockets différents.
La majorité des serveurs crééent 1 process ou un 1 thread séparé par socket pour servir le client (mais il existe une autre manière de faire).

#### Question 2:
listen() ouvre un port en écoute.
accept() est déclenché au moment où un client se connecte effectiement sur ce port (c'est en générale à ce moment là que le serveur créé un nouveau process ou thread).

#### Question 3:
accept() est effectivement bloquant.
C'est pour cette raison que les serveurs forkent ou bien utilisent des threads.
(Mais il existe une autre méthode non bloquant qui n'utilise ni threads ni processes).

Pour le client, connect() est également bloquand (bien qu'il existe également une autre manière de faire, mais assez peu utillisée bien que très pratique).

#### Question 4:
Je ne connais pas bien ipchains, mais tu dois pouvoir définir sur quelle interface ces règles s'appliquent
(par exemple, si tu as 1 modem et une carte réseau, tu peux appliquer la règle de filtrage uniquement sur le modem...)
ça pourrait être une raison pour laquelle ipchains ne bloque pas tes logiciels.

(Mes réponses ne sont sans doute pas complètes.)
1
mathieu
 
Merci pour ces réponses. Il y a quand même un truc qui ne reste pas très clair pour moi (sur la question 1):

lorsque le serveur reçoit une demande de connexion de la part du client (au moment où ce dernier exécute connect), c'est le serveur lui-même qui choisit sur quel port du client il va répondre (dans ton exemple 192.168.0.5:1057) ?

Mais alors pour recevoir cette réponse, il faut que le client écoute sur le port en question (1057) alors qu'il ne sait pas encore que le serveur va répondre sur ce port.

Sinon, j'ai juste une carte réseau branchée sur mon ordinateur qui va ensuite à mon modem cable par lequel je suis connecté à Internet. Les règles ipchains s'appliquent bien à cette carte:
si j'interdis tous les paquets entrants, je ne peux pas recevoir de connections sur mon serveur ftp. En autorisant les paquets entrants sur le port 21, il n'y a plus aucun problème. Donc mon firewall bloque bien les paquets entrants. Mais alors comment se fait il que les clients que j'utilise puissent recevoir des réponses de la part des serveurs alors que tous les ports sont interdits?

Merci
0
sebsauvage
 
C'est le client qui choisit un port au hasard (au dessus de 1024), et non pas le serveur.

Le serveur reçoit une demande de connexion sur son port: cette demande de connexion contient la partie client du socket (IP du client, port du client).

TCP établissant une sorte de canal biridrectionnel, le client n'a pas besoin de se mettre en écoute son port ou sur un autre.
Ils utilisent tous les deux send() et recv() pour envoyer et recevoir les données sur ce canal.
(Comme un téléphone: les deux interlocuteurs ont un micro et un écouteur, et ils peuvent parler en même temps.)

C'est TCP qui fourni cette mécanique bidirectionnelle.
Le client et le serveur possèdent chacun leur socket, et il utilisent indifféremment les méthodes send() et recv() dessus.

Pour la question sur la configuration d'IPchains, est-ce que par hasard ton IP ne serait pas dynamique ?
Si tu as défini des règles de blocage sur une adresse IP et que ton adresse IP a changé, les règles ne seront plus valides, et tout passera sans problème.
(J'ai du mal à diagnostiquer comme ça à la volée...)
0
mathieu
 
Merci pour cette réponse.
Je voudrais savoir par quelle fonction le client fournit au serveur son adresse IP+le numéro de port (la partie client du socket). Est-ce que ce serait automatiquement choisi par le système (c'est ce que signifie ''au hasard"?)?
Dans le tutorial sur les socket que j'ai trouvé sur ce site, il est dit que le client appelle la fonction socket() puis connect(). Mais aucune de ces fonctions ne permet de fournir un numéro de port ou une adresse IP.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
sebsauvage
 
>Je voudrais savoir par quelle fonction le client fournit au serveur son adresse IP+le numéro de port

Il faut lire les RFC concernant TCP (en particulier le format des entêtes TCP ayant le flag SYN (demande de connexion)).
http://rfc.net
http://www.faqs.org

Une autre solution consiste à utiliser Ethereal pour voir dans un cas réel le format des trames (très instructif):
http://www.ethereal.com

>Est-ce que ce serait automatiquement choisi par le système

Oui, et chaque système d'exploitation a sa façon de faire.

>Dans le tutorial sur les socket que j'ai trouvé sur ce site, il est dit
> que le client appelle la fonction socket() puis connect(). Mais
>aucune de ces fonctions ne permet de fournir un numéro de port
>ou une adresse IP.

Si si, dans connect().
0