Gängige auf Ajax (http) basierende Kommunikationsmethoden zwischen Web-Clients und Servern werden in kurze Verbindungen und lange Abfragen unterteilt.
Kurze Verbindung: Jedes Mal, wenn Client und Server einen HTTP-Vorgang ausführen, wird eine Verbindung hergestellt und die Verbindung beendet, wenn die Aufgabe abgeschlossen ist.
Lange Abfrage: Der Client fordert wie bei herkömmlicher Abfrage Daten vom Server an. Wenn der Server jedoch nicht über Daten verfügt, die sofort an den Client zurückgegeben werden können, gibt er nicht sofort ein leeres Ergebnis zurück, sondern lässt die Anforderung auf das Eintreffen der Daten warten (oder auf eine entsprechende Zeitüberschreitung: kleiner als die Ajax-Zeitüberschreitung). , und geben Sie dann die Daten als Ergebnis zurück.
Der lange Abfragemechanismus ist in der folgenden Abbildung dargestellt:
2. Grundkonzepte von WebsocketWebSocket ist ein Protokoll für die Vollduplex-Kommunikation über eine einzelne TCP-Verbindung, das seit Beginn von HTML5 bereitgestellt wird.
WebSocket vereinfacht den Datenaustausch zwischen Client und Server, indem es dem Server ermöglicht, Daten aktiv an den Client zu übertragen. In der WebSocket-API müssen der Browser und der Server lediglich einen Handshake durchführen, und für die bidirektionale Datenübertragung kann direkt eine dauerhafte Verbindung zwischen beiden hergestellt werden.
In der WebSocket-API müssen der Browser und der Server lediglich eine Handshake-Aktion ausführen, und dann wird ein schneller Kanal zwischen dem Browser und dem Server gebildet. Daten können direkt zwischen beiden übertragen werden.
Heutzutage verwenden viele Websites Ajax-Polling, um die Push-Technologie zu implementieren. Beim Polling sendet der Browser in einem bestimmten Zeitintervall (z. B. alle 1 Sekunde) eine HTTP-Anfrage an den Server und der Server sendet dann die neuesten Daten an den Browser des Clients zurück. Dieses traditionelle Modell bringt offensichtliche Mängel mit sich, das heißt, der Browser muss kontinuierlich Anfragen an den Server senden. Allerdings kann die HTTP-Anfrage einen langen Header enthalten, in dem die tatsächlich gültigen Daten möglicherweise nur einen kleinen Teil ausmachen, was offensichtlich eine Verschwendung ist . Viel Bandbreite und andere Ressourcen.
Das von HTML5 definierte WebSocket-Protokoll kann Serverressourcen und Bandbreite besser einsparen und eine Echtzeitkommunikation ermöglichen.
Der Browser sendet eine Anfrage an den Server, um über JavaScript eine WebSocket-Verbindung herzustellen. Nachdem die Verbindung hergestellt wurde, können der Client und der Server direkt Daten über die TCP-Verbindung austauschen.
Nachdem Sie die Web-Socket-Verbindung hergestellt haben, können Sie über die send()-Methode Daten an den Server senden und vom Server zurückgegebene Daten über das onmessage-Ereignis empfangen.
3. Websocket-Handshake-Prinzip:Das Handshake-Prinzip von Websocket lässt sich grob in die folgenden Schritte unterteilen:
Code-Implementierung:
import socket, base64, hashlib# Erstellen Sie eine Socket-Verbindung sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# Binden Sie die Endadresse und die Portnummer sock.bind(('127.0.0.1', 9527))# Hören Sie zu sock.listen (5)# Holen Sie sich das Client-Socket-Objekt conn, Adresse = sock.accept()# Rufen Sie die [Handshake]-Informationen des Clients ab. data = conn.recv(1024)print(data)def get_headers(data): Entfernen Sie den Wert, der Sec-WebSocket-Key entspricht, aus dem Anforderungsheader und geben Sie header_dict = {} header_str = data.decode zurück ( utf8) für i in header_str.split(/r/n): if str(i).startswith(Sec-WebSocket-Key): return i.split(:)[1].strip()# Den Wert abrufen, der Sec-WebSocket-Key entspricht ws_key = get_headers(data)# Der Magic String Magic String lautet: 258EAFA5-E914-47DA-95CA-C5AB0DC85B11magic_string = '258EAFA5 - E914-47DA-95CA-C5AB0DC85B11'# Splicing socket_str = ws_key + magic_string# sha1-Verschlüsselung socket_str_sha1 = hashlib.sha1(socket_str.encode(utf8)).digest()# base64-Verschlüsselung socket_str_base64 = base64.b64encode(socket_str_sha1)# Splicing-Antwortheader Response_tpl = HTTP/1.1 101 Switching Protocols/r/n / Upgrade:websocket/r/n / Verbindung: Upgrade/r/n / Sec-WebSocket-Accept: %s/r/n / WebSocket-Location: ws://127.0.0.1:9527/r /n/r/n % (socket_str_base64.decode(utf8))# Der Server sendet den Antwortheader an den Client conn.send(response_tpl.encode(utf8))# Der Client und der Server stellen eine lange Verbindung her, um Daten in einer Schleife zu empfangen und zu senden, während True: msg = conn.recv(8096) print( Nachricht)
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <title>Title</title></head><body></body><script type=text/javascript> ws = new WebSocket(ws://127.0.0.1:9527); ws.onmessage = function (ev) { console.log(ev)//zum Empfangen von Daten</script></html>
Im Anhang finden Sie den Anforderungsheader für die vom Client initiierte HTTP-Anfrage:
b'GET /ws/ HTTP/1.1Host: 127.0.0.1:9527Connection: UpgradePragma: no-cacheCache-Control: no-cacheUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.3...Upgrade: websocketOrigin : http://localhost:63342Sec-WebSocket-Version: 13Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9Sec-WebSocket-Key: kJXuOKsrl3AR1KeFngRElQ==Sec-WebSocket-Extensions: permessage- deflate; client_max_window_bits'4. Websocket-Verschlüsselungs- und Entschlüsselungsmethoden:
Entschlüsselungsmethode:
# b'/x81/x87/x0e/xc3/xf3/xcd;/xf6/xc6/xf8;/xf6/xc6'==========5555555hashstr = b'/x81/x87/x0e/xc3 /xf3/xcd;/xf6/xc6/xf8;/xf6/xc6'# Führen Sie eine Bitoperation für das zweite Byte aus, nämlich /x87 Bits 9-16 und 127 payload = hashstr[1] & 127# Wenn das Ergebnis der Bitoperation gleich 127 ist, sind die 3-10 Bytes die Datenlänge# Bytes 11-14 sind die für die Maskenentschlüsselung erforderlichen Zeichenfolgen. #Die Daten reichen vom 15. Byte bis zum Ende, wenn Nutzlast == 127: extension_payload_len = hashstr[2:10] mask = hashstr[10:14] decoded = hashstr[14:]# Wenn das Ergebnis der Bitoperation gleich 126 ist, dann sind die 3-4 Bytes die Datenlänge # Die 5-8 Bytes sind die für die Maskenentschlüsselung erforderlichen Zeichenfolgen # Dann die Daten Vom 9. Byte bis zum Ende, wenn Payload == 126: extension_payload_len = hashstr[2:4] mask = hashstr[4:8] decoded = hashstr[8:]# Wenn das Ergebnis der Bitoperation kleiner oder gleich 125 ist, dann ist diese Zahl die Länge der Daten. # Die 3–6 Bytes sind die für die Maskenentschlüsselung erforderliche Zeichenfolge. # Die Daten reichen vom 7. Byte bis zum Ende, wenn Nutzlast <= 125: extension_payload_len = None mask = hashstr[2:6] decoded = hashstr[6:]str_byte = bytearray()for i in range(len(decoded)): byte = decoded[i] ^ mask[i % 4] str_byte.append(byte)print(str_byte.decode(utf8))
Verschlüsselungsmethode:
import structmsg_bytes = 5555555.encode(utf8)token = b/x81length = len(msg_bytes)if length < 126: token += struct.pack(B, length)elif length == 126: token += struct.pack(!BH , 126, Länge)else: token += struct.pack(!BQ, 127, Länge)msg = Token + msg_bytesprint(msg)4. Beispiele für Client- und Server-Link-Kommunikation basierend auf dem Flask-Framework und dem Websocket-Protokoll:
pip3 install gevent-websocket
from flask import Flask, requestfrom geventwebsocket.websocket import WebSocketfrom gevent.pywsgi import WSGIServerfrom geventwebsocket.handler import WebSocketHandlerapp = Flask(__name__)@app.route(/ws)def websocket(): # Holen Sie sich den Link des Benutzers user_socket = request.environ. get(wsgi.websocket) # type:WebSocket print (Zugriff erfolgreich) while True: msg = user_socket.receive() #Nachricht empfangen print(msg) user_socket.send(msg) #Nachricht senden, wenn __name__ == '__main__': # Geben Sie die Adresse und die Portnummer an Öffnen Sie den Websocket-Dienst http_serv = WSGIServer((127.0.0.1, 8001), app, handler_class=WebSocketHandler) # Starten Sie den Websocket-Dienst http_serv.serve_forever()
html-Datei:
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <title>Titel</title> <link href=https://cdnjs.cloudflare.com/ajax/libs/twitter- bootstrap/3.3.7/css/bootstrap.css rel=stylesheet></head><body><botton class=btn btn-default onclick=createsocket()>Klicken Sie hier, um einen Link zu erstellen</botton><br><p>Bitte geben Sie eine Nachricht ein: <input type=text placeholder=Input message id=msg></p><buttom class=btn btn- success onclick =send_msg()>Nachricht senden</buttom><script> var ws = null; function createsocket() { ws = new WebSocket(ws://127.0.0.1:8001/ws); ws.onmessage = function (data) { console.log(message taken from the server=,data.data); } function send_msg() { var to_msg = document.getElementById(msg).value; ws.send(to_msg) }</script></body></html>
client.png
Serverseite.png
Auf diese Weise implementieren wir einfach die Client-Server-Kommunikation über das Websocket-Protokoll. Und wir können mehrere Links erstellen, um gleichzeitig mit der Serverseite zu kommunizieren.
5. Implementieren Sie Instant Messaging (IM) basierend auf Websocket:Servercode:
from flask import Flask, requestfrom geventwebsocket.websocket import WebSocketfrom gevent.pywsgi import WSGIServerfrom geventwebsocket.handler import WebSocketHandlerfrom geventwebsocket.Exceptions import WebSocketErrorimport jsonapp = Flask(__name__)user_socket_dict = {}@app.route(/ws/<username>)def websocket(username): # Holen Sie sich den Link des Benutzers user_socket = request.environ.get(wsgi.websocket) # type:WebSocket user_socket_dict[username] = user_socket print(username+link success!) while True: msg = user_socket.receive() # Nachrichten für Socket in user_socket_dict.values() akzeptieren: # type:WebSocket if user_socket != socket:# Wenn Sie selbst eine Nachricht senden, antwortet Ihnen der Server nicht: socket.send(json.dumps({sender: username, msg: msg})) außer: continueif __name__ == '__main__. ': # Geben Sie die Adresse und Portnummer an, um den Websocket-Dienst http_serv = WSGIServer((127.0.0.1, 8001), app, zu öffnen handler_class=WebSocketHandler) # Starten Sie den Websocket-Dienst http_serv.serve_forever()
HTML-Code:
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <title>Titel</title> <link href=https://cdnjs.cloudflare.com/ajax/libs/twitter- bootstrap/3.3.7/css/bootstrap.css rel=stylesheet></head><body><p>Bitte geben Sie Ihren Spitznamen ein:<input type=text id=username></p><botton class=btn btn-default onclick=createsocket()>Klicken Sie hier, um den Link zu erstellen</botton><br><p>Bitte geben Sie die Nachricht ein: <input type=text id=msg >< /p><buttom class=btn btn-success onclick=send_msg()>Nachricht senden</buttom><br><br><br><div style=border: 2px solid; width: 500px; id=text_div></div><script> var username = null; WebSocket(ws://127.0.0.1:8001/ws + / + Benutzername); ws.onmessage = Funktion (data) { var text_div = document.getElementById(text_div); var obj_data = JSON.parse(data.data); var add_msg = <p> + obj_data.sender + : + obj_data.msg + </p>; innerHTML += add_msg; } } function send_msg() { var to_msg = document.getElementById(msg).value; var text_div = document.getElementById(text_div); var add_msg = <p style='text-align: right'> + to_msg + : + username + </p>; = add_msg; ws.send(to_msg); }</script></body></html>
Client01.png
Client02.png
Serverseite.png
Der Code ist ein Demonstrationscode mit Fehlern und Fehlern. Er wird derzeit hauptsächlich zum Lernen verwendet, daher ist keine Kleinigkeit erlaubt. Wer Interesse hat, kann noch weiter optimieren! ! !
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für das Studium aller hilfreich ist. Ich hoffe auch, dass jeder das VeVb Wulin Network unterstützt.