Ví dụ máy chủ websocket python

Websocket là giao thức chuẩn để trao đổi dữ liệu hai chiều giữa máy khách và máy chủ. Giao thức WebSocket không chạy trên HTTP, thay vào đó nó thực hiện trên giao thức TCP

WebSocket là một kiểu Reverse Ajax

Người ta thường sử dụng Websocket thay vì HTTP cho các trường hợp yêu cầu thời gian thực (thời gian thực). Ví dụ bạn muốn hiển thị biểu đồ, chỉ số chứng khoán, web chat… thì không thể gửi lệnh AJAX liên tiếp tới máy chủ để lấy dữ liệu mới rồi cập nhật lên màn hình, như thế sẽ chiếm nhiều tài nguyên, lưu lượng truy cập

Gói tin của WebSockets nhẹ hơn HTTP rất nhiều, giảm tốc độ mạng đến 3 lần, không cần phải gửi yêu cầu liên tiếp như HTTP

WebSocket là một giao thức truyền thông máy tính, cung cấp các kênh truyền thông full-duplex qua một kết nối TCP duy nhất. Giao thức WebSocket đã được IETF chuẩn hóa thành RFC 6455 vào năm 2011. Đặc tả API hiện tại cho phép các ứng dụng web sử dụng giao thức này được gọi là WebSockets. [1] Đó là một tiêu chuẩn sống được duy trì bởi WHATWG và là người kế thừa API WebSocket từ W3C. [2]

WebSocket khác với HTTP. Cả hai giao thức đều nằm ở lớp 7 trong mô hình OSI và phụ thuộc vào TCP ở lớp 4. Mặc dù chúng khác nhau, nhưng RFC 6455 tuyên bố rằng WebSocket "được thiết kế để hoạt động trên các cổng HTTP 443 và 80 cũng như hỗ trợ trung gian và proxy HTTP", do đó làm cho nó tương thích với HTTP. Để đạt được khả năng tương thích, quá trình bắt tay WebSocket sử dụng tiêu đề Nâng cấp HTTP[3] để thay đổi từ giao thức HTTP sang giao thức WebSocket

Giao thức WebSocket cho phép tương tác giữa trình duyệt web (hoặc ứng dụng khách khác) và máy chủ web với chi phí thấp hơn so với các lựa chọn thay thế bán song công như HTTP polling, tạo điều kiện truyền dữ liệu theo thời gian thực từ và đến máy chủ. Điều này có thể thực hiện được bằng cách cung cấp một cách tiêu chuẩn hóa để máy chủ gửi nội dung đến máy khách mà không cần máy khách yêu cầu trước và cho phép các tin nhắn được truyền qua lại trong khi vẫn giữ kết nối mở. Theo cách này, một cuộc trò chuyện hai chiều đang diễn ra có thể diễn ra giữa máy khách và máy chủ. Các giao tiếp thường được thực hiện qua cổng TCP số 443 (hoặc 80 trong trường hợp kết nối không an toàn), điều này có lợi cho các môi trường chặn kết nối Internet không phải web bằng tường lửa. Giao tiếp trình duyệt-máy chủ hai chiều tương tự đã đạt được theo những cách không được tiêu chuẩn hóa bằng cách sử dụng các công nghệ tạm thời như Comet hoặc Adobe Flash Player. [4]

Hầu hết các trình duyệt đều hỗ trợ giao thức, bao gồm Google Chrome, Firefox, Microsoft Edge, Internet Explorer, Safari và Opera. [5]

Không giống như HTTP, WebSocket cung cấp giao tiếp song công hoàn toàn. [6][7] Ngoài ra, WebSocket cho phép các luồng thư trên TCP. Một mình TCP xử lý các luồng byte không có khái niệm cố hữu về thông báo. Trước WebSocket, giao tiếp song công hoàn toàn cổng 80 có thể đạt được bằng cách sử dụng các kênh Comet; . Giao thức WebSocket nhằm mục đích giải quyết những vấn đề này mà không ảnh hưởng đến các giả định bảo mật của web

Đặc tả giao thức WebSocket xác định

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
0 (WebSocket) và
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
1 (WebSocket Secure) là hai lược đồ định danh tài nguyên thống nhất (URI) mới[8] được sử dụng cho các kết nối không được mã hóa và được mã hóa tương ứng. Ngoài tên sơ đồ và đoạn (i. e.
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
2 không được hỗ trợ), phần còn lại của các thành phần URI được xác định để sử dụng cú pháp chung của URI. [9]

Sử dụng các công cụ dành cho nhà phát triển trình duyệt, các nhà phát triển có thể kiểm tra quá trình bắt tay WebSocket cũng như các khung WebSocket. [10]

Lịch sử[sửa]

WebSocket lần đầu tiên được tham chiếu dưới dạng TCPConnection trong đặc tả HTML5, dưới dạng trình giữ chỗ cho API ổ cắm dựa trên TCP. [11] Vào tháng 6 năm 2008, một loạt các cuộc thảo luận do Michael Carter chủ trì đã dẫn đến phiên bản đầu tiên của giao thức được gọi là WebSocket. [12]

Cái tên "WebSocket" do Ian Hickson và Michael Carter đặt ra ngay sau đó thông qua sự cộng tác trên phòng trò chuyện #whatwg IRC,[13] và sau đó được Ian Hickson cho phép đưa vào đặc tả HTML5. Vào tháng 12 năm 2009, Google Chrome 4 là trình duyệt đầu tiên cung cấp hỗ trợ đầy đủ cho tiêu chuẩn, với WebSocket được bật theo mặc định. [14] Quá trình phát triển giao thức WebSocket sau đó đã được chuyển từ nhóm W3C và WHATWG sang IETF vào tháng 2 năm 2010 và là tác giả của hai bản sửa đổi dưới thời Ian Hickson. [15]

Sau khi giao thức được vận chuyển và bật theo mặc định trong nhiều trình duyệt, RFC 6455 đã được hoàn thiện dưới thời Ian Fette vào tháng 12 năm 2011

RFC 7692 đã giới thiệu tiện ích nén cho WebSocket bằng cách sử dụng thuật toán DEFLATE trên cơ sở mỗi thông báo

Triển khai trình duyệt[sửa]

Phiên bản bảo mật của giao thức WebSocket được triển khai trong Firefox 6,[16] Safari 6, Google Chrome 14,[17] Opera 12. 10 và Internet Explorer 10. [18] Báo cáo bộ kiểm tra giao thức chi tiết[19] liệt kê sự phù hợp của các trình duyệt đó với các khía cạnh giao thức cụ thể

Phiên bản cũ hơn, kém an toàn hơn của giao thức đã được triển khai trong Opera 11 và Safari 5, cũng như phiên bản di động của Safari trong iOS 4. 2. [20] Trình duyệt BlackBerry trong OS7 triển khai WebSockets. [21] Vì các lỗ hổng bảo mật, tính năng này đã bị vô hiệu hóa trong Firefox 4 và 5,[22] và Opera 11. [23]

Trạng thái triển khai Giao thức, phiên bảnNgày soạn thảoInternet ExplorerFirefox[24] (PC)Firefox (Android)Chrome (PC, Di động)Safari (Mac, iOS)Opera (PC, Di động)Trình duyệt Androidhixie-75Ngày 4 tháng 2 năm 201045. 0. 0hixie-76
hybi-00Ngày 6 tháng 5 năm 2010
Ngày 23 tháng 5 năm 20104. 0 (đã tắt)65. 0. 111. 00 (đã tắt)hybi-07, v7Ngày 22 tháng 4 năm 20116[25][a]hybi-10, v8Ngày 11 tháng 7 năm 20117[27][a]714[28]RFC 6455, v13Tháng 12 năm 201110[29]111116[30]612. 10[31]4. 4

Ví dụ về máy khách JavaScript[sửa mã nguồn]

// Creates new WebSocket object with a wss URI as the parameter
const socket = new WebSocket('wss://game.example.com/ws/updates');

// Fired when a connection with a WebSocket is opened
socket.onopen = function () {
  setInterval(function() {
    if (socket.bufferedAmount == 0)
      socket.send(getUpdateData());
  }, 50);
};

// Fired when data is received through a WebSocket
socket.onmessage = function(event) {
  handleUpdateData(event.data);
};

// Fired when a connection with a WebSocket is closed
socket.onclose = function(event) {
  onSocketClose(event);
};

// Fired when a connection with a WebSocket has been closed because of an error
socket.onerror = function(event) {
  onSocketError(event);
};

Triển khai máy chủ web[sửa]

Nginx đã hỗ trợ WebSockets từ năm 2013, được triển khai trong phiên bản 1. 3. 13 [32] bao gồm hoạt động như một proxy ngược và bộ cân bằng tải của các ứng dụng WebSocket. [33]

Máy chủ HTTP Apache đã hỗ trợ WebSockets từ tháng 7 năm 2013, được triển khai trong phiên bản 2. 4. 5 [34][35]

Dịch vụ thông tin Internet đã thêm hỗ trợ cho WebSockets trong phiên bản 8 được phát hành cùng với Windows Server 2012. [36]

lighttpd đã hỗ trợ WebSockets từ năm 2017, được triển khai trong phiên bản 1. 4. 46. [37] lighttpd mod_proxy có thể hoạt động như một proxy ngược và bộ cân bằng tải của các ứng dụng WebSocket. lighttpd mod_wstunnel có thể xây dựng đường hầm WebSocket để truyền dữ liệu tùy ý, kể cả ở định dạng JSON, tới ứng dụng phụ trợ

Tempesta FW hỗ trợ WebSockets cho HTTP/1. 1 và kết nối HTTPS kể từ năm 2022. [38] WebSockets qua HTTP/2 của RFC 8441 được các nhà phát triển coi là chưa được triển khai đủ rộng rãi và đã không được triển khai

Giao thức [ chỉnh sửa ]

Giao thức bắt tay[sửa]

Để thiết lập kết nối WebSocket, máy khách sẽ gửi yêu cầu bắt tay WebSocket, yêu cầu này sẽ được máy chủ trả về phản hồi bắt tay WebSocket, như minh họa trong ví dụ bên dưới. [39]

Yêu cầu của khách hàng (giống như trong HTTP, mỗi dòng kết thúc bằng

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
3 và phải có thêm một dòng trống ở cuối)

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

Phản hồi của máy chủ

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

Quá trình bắt tay bắt đầu bằng một yêu cầu/phản hồi HTTP, cho phép các máy chủ xử lý các kết nối HTTP cũng như các kết nối WebSocket trên cùng một cổng. Sau khi kết nối được thiết lập, giao tiếp sẽ chuyển sang giao thức nhị phân hai chiều không phù hợp với giao thức HTTP

Ngoài các tiêu đề

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
4, máy khách sẽ gửi một tiêu đề
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
5 chứa các byte ngẫu nhiên được mã hóa base64 và máy chủ trả lời bằng hàm băm của khóa trong tiêu đề
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
0. Điều này nhằm ngăn một proxy bộ đệm gửi lại cuộc hội thoại WebSocket trước đó,[40] và không cung cấp bất kỳ xác thực, quyền riêng tư hoặc tính toàn vẹn nào. Hàm băm nối thêm chuỗi cố định
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
1 (UUID) vào giá trị từ tiêu đề
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
5 (không được giải mã từ base64), áp dụng hàm băm SHA-1 và mã hóa kết quả bằng base64. [41]

RFC6455 yêu cầu khóa PHẢI là một nonce bao gồm một giá trị 16 byte được chọn ngẫu nhiên đã được mã hóa base64,[42] là 24 byte trong base64 (với hai byte cuối cùng là

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
3). Mặc dù một số máy chủ HTTP thoải mái cho phép hiển thị các khóa ngắn hơn, nhưng nhiều máy chủ HTTP hiện đại sẽ từ chối yêu cầu với lỗi "tiêu đề Sec-WebSocket-Key không hợp lệ"

Giao thức tạo khung cơ sở[sửa]

Sau khi kết nối được thiết lập, máy khách và máy chủ có thể gửi dữ liệu WebSocket hoặc khung văn bản qua lại ở chế độ song công hoàn toàn. Dữ liệu được đóng khung tối thiểu, với một tiêu đề nhỏ theo sau là tải trọng. [43] Quá trình truyền WebSocket được mô tả là "thông báo", trong đó một thông báo có thể tùy chọn được chia thành nhiều khung dữ liệu. Điều này có thể cho phép gửi tin nhắn khi có sẵn dữ liệu ban đầu nhưng độ dài đầy đủ của tin nhắn là không xác định (nó gửi hết khung dữ liệu này đến khung dữ liệu khác cho đến khi kết thúc và được cam kết với bit FIN)

0123456789ABCDEFFINRSV1RSV2RSV3OpcodeMaskĐộ dài tải trọngĐộ dài tải trọng mở rộng (tùy chọn)Phím ẩn (tùy chọn)Dữ liệu tải trọngFINCho biết đoạn cuối cùng trong thư. 1b. RSVMUST là 0 trừ khi được xác định bởi tiện ích mở rộng. 1b

OpcodeMã hoạt động. 1B

0Khung tiếp tục1Khung văn bản2Khung nhị phân8Đóng kết nối9PingAPongetc. Kín đáo

MaskSet thành 1 nếu dữ liệu tải trọng bị che. 1b

Chiều dài tải trọng Độ dài của dữ liệu tải trọng. 7b

126 2 byte sau đây được hiểu là độ dài tải trọng. 127 8 byte sau đây được hiểu là độ dài tải trọng. 0-125Đây là chiều dài tải trọng

Khóa mặt nạ Tất cả các khung được gửi từ máy khách phải được che bằng phím này. Trường này không có nếu bit mặt nạ được đặt thành 0. 4B. Dữ liệu tải trọng Dữ liệu tải trọng của đoạn

Với các tiện ích mở rộng cho giao thức, điều này cũng có thể được sử dụng để ghép nhiều luồng đồng thời (ví dụ: để tránh độc quyền sử dụng ổ cắm cho một tải trọng lớn). [44]

Mặt nạ máy khách đến máy chủ [ chỉnh sửa ]

Dữ liệu tải trọng được gửi từ máy khách phải được che bằng khóa mặt nạ. Khóa mặt nạ là giá trị ngẫu nhiên 4 byte do khách hàng chọn và không thể đoán trước. Tính không thể đoán trước của khóa mặt nạ là điều cần thiết để ngăn các ứng dụng độc hại chọn các byte đã xuất hiện. Thuật toán sau đây được áp dụng để che giấu dữ liệu tải trọng

j = i MOD 4
transformed-octet-i = original-octet-i XOR masking-key-octet-j

Cân nhắc về bảo mật[sửa | sửa mã nguồn]

Không giống như các yêu cầu HTTP tên miền chéo thông thường, các yêu cầu WebSocket không bị hạn chế bởi chính sách cùng nguồn gốc. Do đó, máy chủ WebSocket phải xác thực tiêu đề "Xuất xứ" dựa trên nguồn gốc dự kiến ​​trong quá trình thiết lập kết nối, để tránh các cuộc tấn công chiếm quyền điều khiển WebSocket trên nhiều trang web (tương tự như giả mạo yêu cầu trên nhiều trang web), điều này có thể xảy ra khi kết nối được xác thực bằng cookie hoặc HTTP . Tốt hơn là sử dụng mã thông báo hoặc cơ chế bảo vệ tương tự để xác thực kết nối WebSocket khi dữ liệu nhạy cảm (riêng tư) được truyền qua WebSocket. [45] Một ví dụ trực tiếp về lỗ hổng đã được nhìn thấy vào năm 2020 dưới dạng Cable Haunt

Truyền tải proxy[sửa]

Việc triển khai máy khách giao thức WebSocket cố gắng phát hiện xem tác nhân người dùng có được định cấu hình để sử dụng proxy khi kết nối với máy chủ và cổng đích hay không và nếu có, hãy sử dụng phương thức HTTP CONNECT để thiết lập đường hầm liên tục

Mặc dù bản thân giao thức WebSocket không biết về máy chủ proxy và tường lửa, nhưng nó có tính năng bắt tay tương thích với HTTP, do đó cho phép máy chủ HTTP chia sẻ cổng HTTP và HTTPS mặc định của chúng (lần lượt là 80 và 443) với cổng hoặc máy chủ WebSocket. Giao thức WebSocket định nghĩa một ws. // và wss. // tiền tố để biểu thị kết nối WebSocket và WebSocket Secure tương ứng. Cả hai lược đồ đều sử dụng cơ chế nâng cấp HTTP để nâng cấp lên giao thức WebSocket. Một số máy chủ proxy trong suốt và hoạt động tốt với WebSocket; . Trong một số trường hợp, có thể yêu cầu cấu hình máy chủ proxy bổ sung và một số máy chủ proxy nhất định có thể cần được nâng cấp để hỗ trợ WebSocket

Nếu lưu lượng truy cập WebSocket không được mã hóa chảy qua một máy chủ proxy rõ ràng hoặc trong suốt mà không có hỗ trợ WebSockets, kết nối có thể sẽ không thành công. [46]

Nếu kết nối WebSocket được mã hóa được sử dụng, thì việc sử dụng Bảo mật tầng vận chuyển (TLS) trong kết nối Bảo mật WebSocket đảm bảo rằng lệnh

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
4 được đưa ra khi trình duyệt được định cấu hình để sử dụng máy chủ proxy rõ ràng. Điều này thiết lập một đường hầm, cung cấp giao tiếp TCP từ đầu đến cuối ở mức độ thấp thông qua proxy HTTP, giữa máy khách WebSocket Secure và máy chủ WebSocket. Trong trường hợp máy chủ proxy trong suốt, trình duyệt không biết máy chủ proxy, vì vậy không có
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
4 nào được gửi. Tuy nhiên, do lưu lượng truy cập dây được mã hóa, các máy chủ proxy trong suốt trung gian có thể chỉ cho phép lưu lượng được mã hóa đi qua, do đó, có nhiều khả năng kết nối WebSocket sẽ thành công nếu sử dụng WebSocket Secure. Sử dụng mã hóa không tốn tài nguyên, nhưng thường mang lại tỷ lệ thành công cao nhất, vì nó sẽ đi qua một đường hầm an toàn

Một bản nháp giữa năm 2010 (phiên bản hixie-76) đã phá vỡ khả năng tương thích với các cổng và proxy đảo ngược bằng cách bao gồm tám byte dữ liệu chính sau các tiêu đề, nhưng không quảng cáo dữ liệu đó trong tiêu đề

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
6. [47] Dữ liệu này không được chuyển tiếp bởi tất cả các bên trung gian, điều này có thể dẫn đến lỗi giao thức. Các bản nháp gần đây hơn (e. g. , hybi-09[48]) đưa dữ liệu chính vào tiêu đề
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
5, giải quyết vấn đề này