Diese Klassifizierung ist eine bequeme Unterteilung von Sockets, die unterschiedlich verwendet werden, und Sockets, die auf diese Weise verwendet werden, werden mit diesen Namen bezeichnet. Das ist. Es ist jedoch klar, dass sich der Listening-Socket in einem anderen Zustand befindet (dh im passiven Modus), da sicher ist, dass er keine Verbindungsanforderung senden kann (Fehler: Transportendpunkt ist bereits verbunden).
Serverseite | Client-Seite | Erläuterung | |
---|---|---|---|
listening socket | listen()Wird dieser Socket durch Ausführen. | ---- | Sie hören einen bestimmten Port. Senden Sie eine Verbindungsanforderung an einen anderen Abhörsocket(connect()Machen)Es ist nicht möglich. Es wird auch gesagt, dass sich die Buchse im passiven Modus befindet oder eine passive Buchse ist. |
connected socket | accept()Dieser Socket wird im Rückgabewert der Funktion übergeben. | connect()Wird ausgeführt und wird zu diesem Socket, indem er auf der Serverseite akzeptiert wird. | Angeschlossene Steckdose. geschickt,Sie können recv usw. tun. |
Alle Steckdosen außer den oben genannten | listen()Steckdose vor dem Laufen | connect()Socket, bevor er von der Serverseite akzeptiert wird | listen()Auch verbinden()Ist auch möglich. hören Sie, hören Sie()Im Falle von binden()Ist notwendig. |
Eine Zeile ist gleichzeitig (kein physikalischer Begriff). Es gibt einige, die nicht eine Zeile sind, sondern fast eine Zeile, aber der Klarheit halber sind sie nicht eine Zeile. In Bezug auf den Status habe ich das Paket mit Wireshark überprüft und es erraten, sodass möglicherweise etwas nicht stimmt. Es gibt verschiedene Methoden zum Schneiden, daher ist dies nur ein Beispiel. Und genau genommen sind die Funktionen, die die Verbindung trennen, "Herunterfahren" und "Schließen". Es scheint, dass der Name "Herunterfahren" realistischer ist und der Name "Schließen" "Zerstören" ist. (https://stackoverflow.com/questions/409783/socket-shutdown-vs-socket-close)
Der Socket-Deskriptor in der Tabelle,
Auf der Serverseite ist listen_sock = socket.socket ()
, linked_sock = listen_sock.accept ()
. Der Socket, auf den listen_sock
verweist, befindet sich jedoch nach listen ()
im Listening-Zustand. Der Grund, warum es zum Zeitpunkt der Socket-Erstellung auf "Listening_Sock" gesetzt ist, ist, dass klar ist, dass danach "listen ()" ausgeführt wird, um ein Listening-Socket zu werden.
Auf der Clientseite ist sock = socket.socket ()
.
Serverseitige Funktionen | Erläuterung | Serverseitiger Status | Clientseitige Funktion | Erläuterung | Client-seitiger Status | |
---|---|---|---|---|---|---|
socket.socket() | Generierung von Steckdosen zum Hören. | CLOSED | socket.socket() | Generieren eines Sockets für die Verbindung. | CLOSED | |
listening_sock.bind() | Benennen der Steckdose. | CLOSED | ---- | ---- | CLOSED | |
listening_sock.listen() | Hier wird die Buchse tatsächlich zu einer Abhörbuchse und beginnt zuzuhören. Das Betriebssystem akzeptiert die Verbindungsanforderung. | LISTENING | ---- | ---- | CLOSED | |
〃 | ---- | LISTENING | sock.connect() | Schließen Sie die Steckdose direkt an die angegebene Adresse an. | SYN SENT | |
〃 | ---- | SYN RECV | 〃 | ---- | SYN SENT | |
〃 | ---- | ESTABLISHED | 〃 | ---- | ESTABLISHED |
Serverseitige Funktionen | Erläuterung | Serverseitiger Status | Clientseitige Funktion | Erläuterung | Client-seitiger Status | |
---|---|---|---|---|---|---|
---- | ---- | ESTABLISHED | ---- | ---- | ESTABLISHED | |
listening_sock.accept() | Akzeptieren Sie die Verbindungsanforderung. | 〃 | ---- | ---- | 〃 | |
---- | ---- | 〃 | sock.sendall() | Senden Sie eine Nachricht an den Server. | 〃 | |
connected_sock.recv() | Empfangen Sie eine Nachricht auf der Client-Seite. | 〃 | ---- | ---- | 〃 | |
connected_sock.sendall() | Senden Sie die Nachricht zurück. | 〃 | ---- | ---- | 〃 | |
---- | ---- | 〃 | sock.recv() | Empfangen von serverseitigen Nachrichten. | 〃 |
Serverseitige Funktionen | Erläuterung | Serverseitiger Status | Clientseitige Funktion | Erläuterung | Client-seitiger Status | |
---|---|---|---|---|---|---|
---- | ---- | ESTABLISHED | ---- | ---- | ESTABLISHED | |
connected_sock.close() | Beenden Sie die Verbindung. Jede Verarbeitung darunter für Socken(recv, send)Kann es auch nicht. | FIN-WAIT-1 | ---- | ---- | ESTABLISHED | |
〃 | ---- | FIN-WAIT-2 | ---- | ---- | CLOSE-WAIT | |
〃 | ---- | FIN-WAIT-2 | sock.close() | Beenden Sie die Verbindung. Jede Verarbeitung darunter für Socken(recv, send)Kann es auch nicht. | LAST-ACK | |
〃 | ---- | TIME-WAIT | 〃 | ---- | ??????? | |
---- | ---- | CLOSED | ---- | ---- | CLOSED |
socket()
Erstellen Sie zunächst einen Socket (den ich nur zum Akzeptieren von Verbindungsanforderungen verwenden möchte, dh einen Listening-Socket).
Der Dateideskriptor, der den erstellten Socket darstellt (referenziert), wird zurückgegeben.
>>> 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" gibt an, dass die Kommunikation IPv4 verwendet, und "SOCK_STREAM" gibt an, dass der Socket ein Socket für die Verbindungstypkommunikation (Stream-Typ-Kommunikation) wie TCP ist. (* Und bieten Vollduplex-Kommunikation)
Sie können sehen, dass die IP-Adresse oder Portnummer von <... laddr = ...>
alle 0 ist. Stellen Sie dies als nächstes ein.
bind()
Weisen Sie dann diesem Socket-Deskriptor eine Adresse zu (Listening_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)>
Sie können sehen, dass (IP-Adresse, Portnummer) in <... laddr = ...>
eingestellt ist.
listen()
Der generierte Socket beginnt an diesem Punkt zu lauschen. Ursprünglich hört es zu diesem Zeitpunkt nur zu und akzeptiert nicht, aber das Betriebssystem akzeptiert die Verbindungsanforderung des Clients im Namen der Anwendung (dh stellt stattdessen eine Verbindung her) und fügt sie der Akzeptanzwarteschlange (Warteschlange) der Anwendung hinzu. Gehen. Das Betriebssystem kann Verbindungsanfragen im Namen der Anwendung bis zu der im Argument "backlog" angegebenen Nummer annehmen. Sobald die Verbindung an die Anwendung übergeben wurde (dh die Anwendung akzeptiert sie), befindet sich ein freier Speicherplatz in der Akzeptanzwarteschlange. Wenn dann die Verbindungsanforderung akzeptiert wird, wird unabhängig vom neuen Überwachungssocket eine neue Verbindung zwischen dem clientseitigen Socket und dem verbundenen Socket hergestellt. Der Überwachungssocket wird für die nächste Verbindungsanforderung neu gestartet und erneut am selben Port. Hör mal zu.
>>> listening_sock.listen(5)
Bei diesem Code beträgt "Backlog" 5, sodass das Betriebssystem Verbindungsanforderungen von 5 clientseitigen Sockets annehmen und in die Akzeptanzwarteschlange stellen kann. Jede weitere Verbindungsanforderung führt zu einem Fehler.
accept()
Wenn accept () ausgeführt wird und das Betriebssystem stattdessen die Verbindungsanforderung akzeptiert, akzeptiert der Deskriptor des verbundenen Sockets der Verbindung oben in der Warteschlange die eingehende Verbindungsanforderung andernfalls und den Deskriptor des verbundenen Sockets der Verbindung. Rückkehr.
>>> connected_sock, client_address = listening_sock.accept()
Im obigen Fall akzeptiert es die Verbindungsanforderung, die an listen_sock eingeht, erstellt einen neuen Socket mit dem Namen connect_sock und stellt eine Verbindung zwischen diesem Socket und dem Socket auf der Clientseite her. (Weder Listening_Sock noch Connected_Sock ist der Socket selbst.) [Hinweis]
Um ehrlich zu sein, verstehe ich diesen Bereich nicht wirklich. Wenn [SYN] an die Hörbuchse kommt, sendet es [SYN, ACK] von der neuen Buchse zurück, um die Verbindung herzustellen? Oder gibt es kein Konzept für eine Steckdose auf der Ebene des 3-Wege-Handshakes? Erstens ist Socket eine API für Programmierer, um für die Anwendung optimierte Kommunikationsprogramme zu erstellen, ohne die komplizierten Teile von TCP (Fenstersteuerung, Flusssteuerung, Neuübertragungssteuerung usw.) und die Teile unter IP im Detail zu kennen. Zum Zeitpunkt des 3-Wege-Handshakes kann es sein, dass nur das Kommunikationsziel durch die Adresse auf der Clientseite bestimmt wird.
socket()
Erstellen Sie zunächst einen Socket. Dann wird der Dateideskriptor zurückgegeben, der den erstellten Socket darstellt (auf diesen verweist).
>>> 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()
Hier wird die Verbindungsanforderung tatsächlich an den Überwachungssocket (der den angegebenen Port überwacht) des Servers gesendet.
>>> sock.connect(server_address)
sendall()
Daten senden.
recv()
Empfange Daten.
close()
Geben Sie Ressourcen für die Verbindung frei. (* Eigentlich müssen Sie vorher shutdown () ausführen. Https://docs.python.org/ja/3/howto/sockets.html#disconnecting)
Recommended Posts