Cette classification est une division pratique des sockets qui sont utilisées différemment, et les sockets qui sont utilisés de cette manière sont désignés par ces noms. C'est. Cependant, il est clair que la socket d'écoute est dans un état différent (c'est-à-dire en mode passif) car il est certain qu'elle ne peut pas ** envoyer une demande de connexion ** (Erreur: le point de terminaison de transport est déjà connecté
).
Du côté serveur | Côté client | Explication | |
---|---|---|---|
listening socket | listen()Devient cette socket en exécutant. | ---- | Vous écoutez un port spécifique. Envoyer une demande de connexion à une autre prise d'écoute(connect()Faire)Ce n'est pas possible. On dit aussi que la prise est en mode passif ou est une prise passive. |
connected socket | accept()Cette socket est passée dans la valeur de retour de la fonction. | connect()Est exécuté, et il devient ce socket en étant accepté côté serveur. | Prise connectée. envoyé,Vous pouvez faire recv etc. |
Toutes les prises autres que celles ci-dessus | listen()Prise avant de courir | connect()Socket avant d'être accepté par le serveur | listen()Connectez également()Est également possible. écoute écoute()Dans le cas de bind()Est nécessaire. |
Une ligne est en même temps (pas un terme de physique). Il y en a qui ne sont pas une ligne, mais presque une ligne, mais ce ne sont pas une ligne par souci de clarté. En ce qui concerne l'état, j'ai vérifié le paquet avec Wireshark et je l'ai deviné, il peut donc y avoir quelque chose qui ne va pas. Il existe différentes méthodes de découpe, ce n'est donc qu'un exemple. Et, à proprement parler, les fonctions qui déconnectent la connexion sont «shutdown» et «close». Il semble que le nom «shutdown» soit plus réaliste et que le nom «close» soit «destroy». (https://stackoverflow.com/questions/409783/socket-shutdown-vs-socket-close)
Le descripteur de socket dans le tableau,
Côté serveur, listen_sock = socket.socket ()
, connected_sock = listen_sock.accept ()
. Cependant, la socket référencée par listen_sock
est dans l'état d'écoute après listen ()
. La raison pour laquelle il est réglé sur listen_sock
au moment de la création de la socket est qu'il est clair qu'après cela,listen ()
est exécuté pour devenir une socket d'écoute.
Du côté client se trouve sock = socket.socket ()
.
Fonctions côté serveur | Explication | État côté serveur | Fonction côté client | Explication | Statut côté client | |
---|---|---|---|---|---|---|
socket.socket() | Génération de prises pour l'écoute. | CLOSED | socket.socket() | Générer une prise pour la connexion. | CLOSED | |
listening_sock.bind() | Nommer le socket. | CLOSED | ---- | ---- | CLOSED | |
listening_sock.listen() | Ici, la prise devient en fait une prise d'écoute et commence à écouter. Le système d'exploitation accepte la demande de connexion. | LISTENING | ---- | ---- | CLOSED | |
〃 | ---- | LISTENING | sock.connect() | Connectez la prise directement à l'adresse spécifiée. | SYN SENT | |
〃 | ---- | SYN RECV | 〃 | ---- | SYN SENT | |
〃 | ---- | ESTABLISHED | 〃 | ---- | ESTABLISHED |
Fonctions côté serveur | Explication | État côté serveur | Fonction côté client | Explication | Statut côté client | |
---|---|---|---|---|---|---|
---- | ---- | ESTABLISHED | ---- | ---- | ESTABLISHED | |
listening_sock.accept() | Acceptez la demande de connexion. | 〃 | ---- | ---- | 〃 | |
---- | ---- | 〃 | sock.sendall() | Envoyez un message au serveur. | 〃 | |
connected_sock.recv() | Recevez un message côté client. | 〃 | ---- | ---- | 〃 | |
connected_sock.sendall() | Renvoyez le message. | 〃 | ---- | ---- | 〃 | |
---- | ---- | 〃 | sock.recv() | Recevez des messages côté serveur. | 〃 |
Fonctions côté serveur | Explication | État côté serveur | Fonction côté client | Explication | Statut côté client | |
---|---|---|---|---|---|---|
---- | ---- | ESTABLISHED | ---- | ---- | ESTABLISHED | |
connected_sock.close() | Mettez fin à la connexion. Tout traitement ci-dessous pour la chaussette(recv, send)Je ne peux pas le faire non plus. | FIN-WAIT-1 | ---- | ---- | ESTABLISHED | |
〃 | ---- | FIN-WAIT-2 | ---- | ---- | CLOSE-WAIT | |
〃 | ---- | FIN-WAIT-2 | sock.close() | Mettez fin à la connexion. Tout traitement ci-dessous pour la chaussette(recv, send)Je ne peux pas le faire non plus. | LAST-ACK | |
〃 | ---- | TIME-WAIT | 〃 | ---- | ??????? | |
---- | ---- | CLOSED | ---- | ---- | CLOSED |
socket()
Tout d'abord, créez une socket (que j'ai l'intention d'utiliser uniquement pour accepter les demandes de connexion, c'est-à-dire une prise d'écoute).
Le descripteur de fichier qui représente (référence) le socket créé est renvoyé.
>>> listening_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> listening_sock
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 0)>
«AF_INET» indique que la communication utilise IPv4, et «SOCK_STREAM» indique que le socket est un socket pour une communication de type connexion (communication de type flux) telle que TCP. (* Et fournir une communication en duplex intégral)
Vous pouvez voir que l'adresse IP ou le numéro de port de <... laddr = ...>
est tout à 0, définissez-le ensuite.
bind()
Attribuez ensuite une adresse à ce descripteur de socket (écoute_sock).
>>> listening_sock.bind(('127.0.0.1', 8000))
>>> listening_sock
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8000)>
Vous pouvez voir que (adresse IP, numéro de port) est défini dans <... laddr = ...>
.
listen()
Le socket généré commence à écouter à ce stade. À l'origine, à ce stade, il écoute et n'accepte pas, mais le système d'exploitation accepte la demande de connexion du client au nom de l'application (c'est-à-dire se connecte à la place) et l'ajoute à la file d'attente d'acceptation de l'application (file d'attente) Aller. Le système d'exploitation peut accepter les demandes de connexion au nom de l'application jusqu'au nombre indiqué dans l'argument backlog
. Une fois la connexion transmise à l'application (c'est-à-dire que l'application l'accepte), il y a un espace libre dans la file d'attente d'acceptation. Ensuite, lorsque la demande de connexion est acceptée, une nouvelle connexion est créée entre le socket côté client et le socket connecté indépendamment du nouveau socket d'écoute, le socket d'écoute redémarre pour la demande de connexion suivante, et à nouveau sur le même port. Ecoutez.
>>> listening_sock.listen(5)
Dans le cas de ce code, backlog
est 5, donc le système d'exploitation peut accepter les demandes de connexion de 5 sockets côté client et les mettre dans la file d'attente d'acceptation. Toute autre demande de connexion entraînera une erreur.
accept()
Lorsque accept () est exécuté, si l'OS accepte la demande de connexion à la place, le descripteur du socket connecté de la connexion en haut de la file d'attente accepte la demande de connexion entrante dans le cas contraire, et accepte le descripteur du socket connecté de la connexion. revenir.
>>> connected_sock, client_address = listening_sock.accept()
Dans le cas ci-dessus, il accepte la demande de connexion qui arrive à listen_sock, crée un nouveau socket appelé connected_sock et établit une connexion entre ce socket et le socket côté client. (Ni listen_sock ni connected_sock ne sont en fait la socket elle-même) [Note]
Pour être honnête, je ne comprends pas vraiment ce domaine. Lorsque [SYN] arrive sur la prise d'écoute, renverra-t-il [SYN, ACK] depuis la nouvelle prise pour établir la connexion? Ou n'y a-t-il pas de concept de socket au niveau de la poignée de main à 3 voies? En premier lieu, socket est une API permettant aux programmeurs de créer des programmes de communication optimisés pour l'application sans connaître en détail les parties compliquées de TCP (contrôle de fenêtre, contrôle de flux, contrôle de retransmission, etc.) et les parties sous IP. Au moment de la prise de contact à 3 voies, il se peut que seule la destination de communication soit déterminée par l'adresse côté client.
socket()
Commencez par créer une socket. Ensuite, le descripteur de fichier représentant (faisant référence à) la socket créée est retourné.
>>> listening_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> listening_sock
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 0)>
connect()
Ici, la demande de connexion est effectivement envoyée au socket d'écoute (écoutant le port spécifié) du serveur.
>>> sock.connect(server_address)
sendall()
Envoyer des données.
recv()
Recevoir des données.
close()
Libérez les ressources liées à la connexion. (* En fait, vous devez faire shutdown () avant cela. Https://docs.python.org/ja/3/howto/sockets.html#disconnecting)
Recommended Posts