تنقسم طرق الاتصال الشائعة المستندة إلى Ajax (http) بين عملاء الويب والخوادم إلى اتصالات قصيرة واستقصاء طويل .
اتصال قصير: في كل مرة يقوم فيها العميل والخادم بإجراء عملية HTTP، يتم إنشاء اتصال، ويتم إنهاء الاتصال عند اكتمال المهمة.
الاستقصاء الطويل: يطلب العميل البيانات من الخادم مثل الاستقصاء التقليدي. ومع ذلك، إذا لم يكن لدى الخادم بيانات يمكن إعادتها إلى العميل على الفور، فلن يُرجع نتيجة فارغة على الفور، ولكنه سيبقي الطلب في انتظار وصول البيانات (أو مهلة مناسبة: أقل من مهلة أجاكس) ، ثم قم بإرجاع البيانات كنتيجة للعميل.
وتظهر آلية الاقتراع الطويل في الشكل أدناه:
2. المفاهيم الأساسية لـ WebsocketWebSocket هو بروتوكول للاتصال مزدوج الاتجاه على اتصال TCP واحد بدأ HTML5 في توفيره.
يجعل WebSocket تبادل البيانات بين العميل والخادم أكثر بساطة، مما يسمح للخادم بدفع البيانات إلى العميل بشكل فعال. في WebSocket API، يحتاج المتصفح والخادم فقط إلى إكمال المصافحة، ويمكن إنشاء اتصال مستمر مباشرة بين الاثنين لنقل البيانات ثنائي الاتجاه.
في WebSocket API، يحتاج المتصفح والخادم فقط إلى تنفيذ إجراء المصافحة، ثم يتم تشكيل قناة سريعة بين المتصفح والخادم. يمكن نقل البيانات مباشرة بين الاثنين.
في الوقت الحاضر، من أجل تنفيذ تقنية الدفع، تستخدم العديد من مواقع الويب استطلاعات Ajax. يتم الاستقصاء عندما يصدر المتصفح طلب HTTP إلى الخادم في فترة زمنية محددة (مثل كل ثانية واحدة)، ثم يقوم الخادم بإرجاع أحدث البيانات إلى متصفح العميل. يحتوي هذا النموذج التقليدي على عيوب واضحة، حيث يحتاج المتصفح إلى إرسال الطلبات بشكل مستمر إلى الخادم، ومع ذلك، قد يحتوي طلب HTTP على رأس طويل، حيث قد تكون البيانات الحقيقية الحقيقية جزءًا صغيرًا فقط، وهو ما يعد مضيعة بشكل واضح. وهناك الكثير من عرض النطاق الترددي وغيرها من الموارد.
يمكن لبروتوكول WebSocket المحدد بواسطة HTML5 توفير موارد الخادم وعرض النطاق الترددي بشكل أفضل، وتمكين المزيد من الاتصالات في الوقت الفعلي.
يرسل المتصفح طلبًا إلى الخادم لإنشاء اتصال WebSocket من خلال JavaScript. بعد إنشاء الاتصال، يمكن للعميل والخادم تبادل البيانات مباشرة من خلال اتصال TCP.
بعد الحصول على اتصال WebSocket، يمكنك إرسال البيانات إلى الخادم من خلال طريقة الإرسال () وتلقي البيانات التي يتم إرجاعها بواسطة الخادم من خلال حدث onmessage.
3. مبدأ المصافحة Websocket:يمكن تقسيم مبدأ المصافحة في Websocket تقريبًا إلى الخطوات التالية:
تنفيذ الكود:
import مقبس, base64, hashlib# إنشاء اتصال مأخذ توصيل sock = المقبس.socket(socket.AF_INET, المقبس.SOCK_STREAM)# ربط عنوان النهاية ورقم المنفذ sock.bind(('127.0.0.1', 9527))# استمع إلى sock.listen (5)# احصل على كائن مقبس العميل conn، العنوان = sock.accept()# احصل على معلومات معلومات [المصافحة] الخاصة بالعميل = conn.recv(1024)print(data)def get_headers(data): قم بإزالة القيمة المقابلة لـ Sec-WebSocket-Key من رأس الطلب وإرجاع header_dict = {} header_str = data.decode ( utf8) لـ i في header_str.split(/r/n): إذا str(i).startswith(Sec-WebSocket-Key): العودة i.split(:)[1].strip()# احصل على القيمة المقابلة لـ Sec-WebSocket-Key ws_key = get_headers(data)# السلسلة السحرية للسلسلة السحرية هي: 258EAFA5-E914-47DA-95CA-C5AB0DC85B11magic_string = '258EAFA5 - E914-47DA-95CA-C5AB0DC85B11'# الربط المقبس_str = ws_key + magic_string# التشفير sha1 مقبس_str_sha1 = hashlib.sha1(socket_str.encode(utf8)).digest()# التشفير base64 المقبس_str_base64 = base64.b64encode(socket_str_sha1)# رأس الاستجابة الربط Response_tpl = HTTP/1.1 101 التبديل البروتوكولات/r/n / الترقية:websocket/r/n / الاتصال: ترقية/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))# يرسل الخادم رأس الاستجابة إلى العميل conn.send(response_tpl.encode(utf8))# ينشئ العميل والخادم اتصالاً طويلًا لتلقي البيانات وإرسالها في حلقة بينما True: msg = conn.recv(8096) print( رسالة) <!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <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)//لتلقي البيانات</script></html>مرفق رأس الطلب لطلب HTTP الذي بدأه العميل:
b'GET /ws/ HTTP/1.1Host: 127.0.0.1:9527 الاتصال: UpgradePragma: no-cacheCache-Control: no-cacheUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.3...الترقية: 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- انكماش؛client_max_window_bits'4. طرق تشفير وفك تشفير Websocket:
طريقة فك التشفير:
# 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'# قم بإجراء عملية بت على البايت الثاني، وهو /x87 بت 9-16، و127 payload = hashstr[1] & 127# عندما تكون نتيجة عملية البت تساوي 127، فإن 3-10 بايت هي طول البيانات # بايت 11-14 هي السلسلة المطلوبة لفك تشفير القناع # البيانات من البايت الخامس عشر إلى النهاية إذا كانت الحمولة == 127: Extend_payload_len = hashstr[2:10] Mask = hashstr[10:14] decoded = hashstr[14:]# عندما تكون نتيجة عملية البت تساوي 126، فإن 3-4 بايت هي طول البيانات # 5-8 بايت هي السلسلة المطلوبة لفك تشفير القناع # ثم البيانات من البايت التاسع حتى النهاية إذا كانت الحمولة == 126: Extend_payload_len = hashstr[2:4] قناع = hashstr[4:8] decoded = hashstr[8:]# عندما تكون نتيجة عملية البت أقل من أو تساوي 125، فإن هذا الرقم هو طول البيانات # 3-6 بايت هي السلسلة المطلوبة لفك تشفير القناع # البيانات من البايت السابع إلى النهاية إذا كانت الحمولة <= 125: Extend_payload_len = لا يوجد قناع = hashstr[2:6] decoded = hashstr[6:]str_byte = bytearray()for i in range(len(decoded)): byte = decoded[i] ^ قناع[i] % 4] str_byte.append(byte)print(str_byte.decode(utf8))
طريقة التشفير:
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، الطول) آخر: الرمز المميز += struct.pack(!BQ, 127, length)msg = الرمز المميز + msg_bytesprint(msg)4. أمثلة على اتصالات ارتباط العميل والخادم بناءً على إطار عمل القارورة وبروتوكول Websocket:
pip3 install gevent-websocket
من قارورة استيراد قارورة، طلب من geventwebsocket.websocket import WebSocketfrom gevent.pywsgi import WSGIServerfrom geventwebsocket.handler import WebSocketHandlerapp = Flask(__name__)@app.route(/ws)def websocket(): # احصل على رابط المستخدم user_socket = request.environ. الحصول على (wsgi.websocket) # type:WebSocket print (تم الوصول بنجاح) while True: msg = user_socket.receive() #Receive message print(msg) user_socket.send(msg) #Send message if __name__ == '__main__': # حدد العنوان ورقم المنفذ إلى افتح خدمة Websocket http_serv = WSGIServer((127.0.0.1، 8001)، التطبيق، Handler_class=WebSocketHandler) # ابدأ خدمة Websocket http_serv.serve_forever()
ملف أتش تي أم أل:
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <title>العنوان</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()>انقر لإنشاء رابط</botton><br><p>الرجاء إدخال رسالة: <input type=text placeholder=Input message id=msg></p><buttom class=btn btn- Success onclick =send_msg()>إرسال رسالة</buttom><script> var ws = null function createocket() { ws = new WebSocket(ws://127.0.0.1:8001/ws); ws.onmessage = function (data) { console.log(message الوارد من الخادم=,data.data); document.getElementById(msg).value ws.send(to_msg) </script></body></html> Client.png
جانب الخادم.png
بهذه الطريقة، نقوم ببساطة بتنفيذ الاتصال بين العميل والخادم من خلال بروتوكول Websocket. ويمكننا إنشاء روابط متعددة للتواصل مع الخادم في نفس الوقت.
5. تنفيذ المراسلة الفورية (IM) استنادًا إلى Websocket:رمز الخادم:
من قارورة استيراد قارورة، طلب من geventwebsocket.websocket استيراد WebSocketمن gevent.pywsgi استيراد WSGIServerمن geventwebsocket.handler استيراد WebSocketHandlerمن geventwebsocket.exceptions import WebSocketErrorimport jsonapp = Flask(__name__)user_socket_dict = {}@app.route(/ws/<username>)def websocket(username): # احصل على رابط المستخدم user_socket = request.environ.get(wsgi.websocket) # type:WebSocket user_socket_dict[username] = user_socket print(username+link نجح!) while True: msg = user_socket.receive() # قبول الرسائل للمقبس في user_socket_dict.values(): # type:WebSocket if user_socket!= المقبس:# إذا أرسلت رسالة بنفسك، فلن يرد عليك الخادم حاول: مقبس.send(json.dumps({sender: username, msg: msg})) باستثناء: continueif __name__ == '__main__. ': # حدد العنوان ورقم المنفذ لفتح خدمة Websocket http_serv = WSGIServer((127.0.0.1, 8001), app, Handler_class=WebSocketHandler) # ابدأ خدمة Websocket http_serv.serve_forever()كود أتش تي أم أل:
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <title>العنوان</title> <link href=https://cdnjs.cloudflare.com/ajax/libs/twitter- bootstrap/3.3.7/css/bootstrap.css rel=stylesheet></head><body><p>الرجاء إدخال لقبك:<input type=text id=username></p><botton class=btn btn-default onclick=createsocket()>انقر لإنشاء الرابط</botton><br><p>الرجاء إدخال الرسالة: <input type=text id=msg >< /p><buttom class=btn btn-success onclick=send_msg()>أرسل رسالة</buttom><br><br><br><div style=border: 2px Solid; width: 500px; height: 800px; id=text_div></div><script> var ws = null; function createocket() { username = document.getElementById(username).value; WebSocket(ws://127.0.0.1:8001/ws + / + username); (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>; InternalHTML += 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); Client01.png
Client02.png
جانب الخادم.png
الكود عبارة عن كود توضيحي، به أخطاء وأخطاء، وهو يستخدم بشكل أساسي للتعلم في الوقت الحالي، لذلك لا يُسمح بالتصيد. يمكن لأولئك المهتمين إجراء المزيد من التحسين! ! !
ما ورد أعلاه هو المحتوى الكامل لهذه المقالة وآمل أن يكون مفيدًا لدراسة الجميع وآمل أيضًا أن يدعم الجميع شبكة VeVb Wulin.