Việc gửi dữ liệu giữa hai trình duyệt để giao tiếp, chơi trò chơi hoặc chuyển tệp có thể là một quá trình khá phức tạp. Bạn cần thiết lập và trả phí cho một máy chủ để chuyển tiếp dữ liệu, đồng thời có thể mở rộng quy mô cho nhiều trung tâm dữ liệu. Trong trường hợp này, có thể xảy ra độ trễ cao và khó giữ bí mật dữ liệu.
Bạn có thể giảm thiểu các vấn đề này bằng cách sử dụng API RTCDataChannel
của WebRTC để truyền dữ liệu trực tiếp từ máy khách này sang máy khách khác. Bài viết này trình bày các kiến thức cơ bản về cách thiết lập và sử dụng kênh dữ liệu, cũng như các trường hợp sử dụng phổ biến trên web hiện nay.
Tại sao lại cần một kênh dữ liệu khác?
Chúng ta có WebSocket, AJAX và Sự kiện do máy chủ gửi. Tại sao chúng ta cần một kênh liên lạc khác? WebSocket là hai chiều, nhưng tất cả các công nghệ này đều được thiết kế để giao tiếp với hoặc từ máy chủ.
RTCDataChannel
sử dụng một phương pháp khác:
- API này hoạt động với API
RTCPeerConnection
, cho phép kết nối ngang hàng. Điều này có thể làm giảm độ trễ – không có máy chủ trung gian và ít "điểm chuyển tiếp" hơn. RTCDataChannel
sử dụng Giao thức truyền điều khiển luồng (SCTP), cho phép cấu hình phân phối ngữ nghĩa-phân phối không theo thứ tự và cấu hình truyền lại.
RTCDataChannel
hiện có hỗ trợ SCTP trên máy tính và Android trong Google Chrome, Opera và Firefox.
Cảnh báo: Báo hiệu, STUN và TURN
WebRTC cho phép giao tiếp ngang hàng, nhưng vẫn cần máy chủ để gửi tín hiệu nhằm trao đổi nội dung nghe nhìn và siêu dữ liệu mạng để khởi động một kết nối ngang hàng.
WebRTC xử lý NAT và tường lửa bằng:
- Khung ICE để thiết lập đường dẫn mạng tốt nhất có thể giữa các máy ngang hàng.
- Máy chủ STUN để xác định một địa chỉ IP và cổng có thể truy cập công khai cho mỗi máy ngang hàng.
- Máy chủ TURN nếu không kết nối được trực tiếp và cần chuyển tiếp dữ liệu.
Để biết thêm thông tin về cách WebRTC hoạt động với các máy chủ để báo hiệu và kết nối mạng, hãy xem bài viết WebRTC trong thực tế: STUN, TURN và báo hiệu.
Các chức năng
API RTCDataChannel
hỗ trợ một tập hợp các loại dữ liệu linh hoạt. API này được thiết kế để mô phỏng chính xác WebSocket và RTCDataChannel
hỗ trợ chuỗi cũng như một số loại tệp nhị phân trong JavaScript, chẳng hạn như Blob, ArrayBuffer và ArrayBufferView. Các loại này có thể hữu ích khi bạn chuyển tệp và chơi trò chơi nhiều người chơi.
RTCDataChannel
có thể hoạt động ở chế độ không đáng tin cậy và không theo thứ tự (tương tự như Giao thức dữ liệu người dùng hoặc UDP), chế độ đáng tin cậy và có thứ tự (tương tự như Giao thức điều khiển truyền tải hoặc TCP) và các chế độ đáng tin cậy một phần:
- Chế độ đáng tin cậy và có thứ tự đảm bảo việc truyền tin nhắn cũng như thứ tự phân phối tin nhắn. Điều này làm tăng thêm chi phí, do đó có thể làm cho chế độ này chậm hơn.
- Chế độ không đáng tin cậy và không theo thứ tự không đảm bảo mọi thông báo đều được gửi đến phía bên kia cũng như thứ tự gửi thông báo. Điều này giúp loại bỏ hao tổn, cho phép chế độ này hoạt động nhanh hơn nhiều.
- Chế độ đáng tin cậy một phần đảm bảo việc truyền thông báo trong một điều kiện cụ thể, chẳng hạn như thời gian chờ truyền lại hoặc số lần truyền lại tối đa. Bạn cũng có thể định cấu hình thứ tự của các thông báo.
Hiệu suất của hai chế độ đầu tiên gần như giống nhau khi không có gói dữ liệu nào bị mất. Tuy nhiên, ở chế độ đáng tin cậy và có thứ tự, một gói bị mất sẽ khiến các gói khác bị chặn phía sau gói đó và gói bị mất có thể đã lỗi thời vào thời điểm được truyền lại và đến nơi. Tất nhiên, bạn có thể sử dụng nhiều kênh dữ liệu trong cùng một ứng dụng, mỗi kênh có ngữ nghĩa đáng tin cậy hoặc không đáng tin cậy riêng.
Dưới đây là bảng hữu ích trong bài viết High Performance Browser Networking (Mạng truyền tải trình duyệt hiệu suất cao) của Ilya Grigorik:
TCP | UDP | SCTP | |
Độ tin cậy | Đáng tin cậy | Không đáng tin cậy | Có thể định cấu hình |
Giao hàng | Đã đặt hàng | Không theo thứ tự | Có thể định cấu hình |
Hệ thống truyền động | Định hướng theo byte | Định hướng theo thông điệp | Định hướng theo thông điệp |
Kiểm soát luồng | Có | Không | Có |
Kiểm soát tình trạng tắc nghẽn | Có | Không | Có |
Tiếp theo, bạn sẽ tìm hiểu cách định cấu hình RTCDataChannel
để sử dụng chế độ đáng tin cậy và có thứ tự hoặc không đáng tin cậy và không có thứ tự.
Định cấu hình kênh dữ liệu
Có một số bản minh hoạ đơn giản về RTCDataChannel
trên mạng:
Trong các ví dụ này, trình duyệt tạo một kết nối ngang hàng với chính nó, sau đó tạo một kênh dữ liệu và gửi thông báo thông qua kết nối ngang hàng. Sau đó, ứng dụng này sẽ tạo một kênh dữ liệu và gửi thông báo dọc theo kết nối ngang hàng. Cuối cùng, thông báo của bạn sẽ xuất hiện trong hộp ở phía bên kia của trang!
Mã để bắt đầu với tính năng này rất ngắn:
const peerConnection = new RTCPeerConnection();
// Establish your peer connection using your signaling channel here
const dataChannel =
peerConnection.createDataChannel("myLabel", dataChannelOptions);
dataChannel.onerror = (error) => {
console.log("Data Channel Error:", error);
};
dataChannel.onmessage = (event) => {
console.log("Got Data Channel Message:", event.data);
};
dataChannel.onopen = () => {
dataChannel.send("Hello World!");
};
dataChannel.onclose = () => {
console.log("The Data Channel is Closed");
};
Đối tượng dataChannel
được tạo từ một kết nối ngang hàng đã được thiết lập. Bạn có thể tạo trước hoặc sau khi tín hiệu xảy ra. Sau đó, bạn truyền vào một nhãn để phân biệt kênh này với các kênh khác và một tập hợp các chế độ cài đặt cấu hình không bắt buộc:
const dataChannelOptions = {
ordered: false, // do not guarantee order
maxPacketLifeTime: 3000, // in milliseconds
};
Bạn cũng có thể thêm tuỳ chọn maxRetransmits
(số lần thử trước khi không thành công), nhưng bạn chỉ có thể chỉ định maxRetransmits hoặc maxPacketLifeTime, chứ không thể chỉ định cả hai. Đối với ngữ nghĩa UDP, hãy đặt maxRetransmits
thành 0
và ordered
thành false
. Để biết thêm thông tin, hãy xem các RFC IETF sau: Giao thức truyền tải điều khiển luồng và Tiện ích độ tin cậy một phần của Giao thức truyền tải điều khiển luồng.
ordered
: liệu kênh dữ liệu có đảm bảo thứ tự hay khôngmaxPacketLifeTime
: thời gian tối đa để thử và truyền lại một thông báo không thành côngmaxRetransmits
: số lần tối đa để thử và truyền lại một thông báo không thành côngprotocol
: cho phép sử dụng một giao thức phụ cung cấp thông tin siêu dữ liệu cho ứng dụngnegotiated
: nếu được đặt thành true, sẽ xoá chế độ tự động thiết lập kênh dữ liệu trên máy ngang hàng khác, cung cấp cách riêng để tạo kênh dữ liệu có cùng mã nhận dạng ở phía bên kiaid
: cho phép bạn cung cấp mã nhận dạng của riêng mình cho kênh. Mã nhận dạng này chỉ có thể được sử dụng kết hợp vớinegotiated
được đặt thànhtrue
)
Các tuỳ chọn duy nhất mà hầu hết mọi người cần sử dụng là 3 tuỳ chọn đầu tiên: ordered
, maxPacketLifeTime
và maxRetransmits
. Với SCTP (hiện được tất cả trình duyệt hỗ trợ WebRTC sử dụng), đáng tin cậy và có thứ tự là đúng theo mặc định. Bạn nên sử dụng không đáng tin cậy và không theo thứ tự nếu muốn có toàn quyền kiểm soát từ lớp ứng dụng, nhưng trong hầu hết các trường hợp, độ tin cậy một phần sẽ hữu ích.
Xin lưu ý rằng, giống như WebSocket, RTCDataChannel
sẽ kích hoạt các sự kiện khi một kết nối được thiết lập, đóng hoặc gặp lỗi và khi nhận được thông báo từ máy chủ đồng cấp khác.
Thử thách này có an toàn không?
Tất cả thành phần WebRTC đều bắt buộc phải mã hoá. Với RTCDataChannel
, tất cả dữ liệu đều được bảo mật bằng Giao thức bảo mật tầng truyền tải gói thông tin (DTLS). DTLS là một dẫn xuất của SSL, nghĩa là dữ liệu của bạn sẽ an toàn như khi sử dụng bất kỳ kết nối dựa trên SSL tiêu chuẩn nào. DTLS được chuẩn hoá và tích hợp vào tất cả trình duyệt hỗ trợ WebRTC. Để biết thêm thông tin, hãy xem Wireshark wiki.
Thay đổi cách bạn suy nghĩ về dữ liệu
Việc xử lý lượng lớn dữ liệu có thể là một điểm khó khăn trong JavaScript. Như các nhà phát triển của Sharefest đã chỉ ra, điều này đòi hỏi phải suy nghĩ về dữ liệu theo cách mới. Nếu đang chuyển một tệp lớn hơn dung lượng bộ nhớ có sẵn, bạn phải nghĩ đến những cách mới để lưu thông tin này. Đây là nơi các công nghệ, chẳng hạn như FileSystem API, phát huy tác dụng, như bạn sẽ thấy trong phần tiếp theo.
Tạo ứng dụng chia sẻ tệp
Giờ đây, bạn có thể tạo một ứng dụng web có thể chia sẻ tệp trong trình duyệt bằng RTCDataChannel
. Việc xây dựng dựa trên RTCDataChannel
có nghĩa là dữ liệu tệp được chuyển sẽ được mã hoá và không chạm vào máy chủ của nhà cung cấp ứng dụng. Chức năng này, kết hợp với khả năng kết nối với nhiều ứng dụng để chia sẻ nhanh hơn, giúp tính năng chia sẻ tệp WebRTC trở thành một ứng dụng mạnh mẽ cho web.
Bạn cần thực hiện một số bước để chuyển thành công:
- Đọc tệp trong JavaScript bằng File API (API Tệp).
- Tạo kết nối ngang hàng giữa các ứng dụng bằng
RTCPeerConnection
. - Tạo kênh dữ liệu giữa các ứng dụng bằng
RTCDataChannel
.
Có một vài điểm cần cân nhắc khi cố gắng gửi tệp qua RTCDataChannel
:
- Kích thước tệp: nếu kích thước tệp nhỏ hợp lý và có thể được lưu trữ và tải dưới dạng một Blob, thì bạn có thể tải vào bộ nhớ bằng File API, sau đó gửi tệp đó qua một kênh đáng tin cậy (mặc dù hãy lưu ý rằng trình duyệt áp đặt giới hạn về kích thước chuyển tối đa). Khi kích thước tệp lớn hơn, mọi thứ sẽ trở nên phức tạp hơn. Khi cần có cơ chế phân đoạn, các phân đoạn tệp sẽ được tải và gửi đến một máy ngang hàng khác, kèm theo siêu dữ liệu
chunkID
để máy ngang hàng có thể nhận ra các phân đoạn đó. Xin lưu ý rằng trong trường hợp này, trước tiên, bạn cũng cần lưu các đoạn vào bộ nhớ ngoại tuyến (ví dụ: sử dụng FileSystem API) và chỉ lưu vào ổ đĩa của người dùng khi bạn có toàn bộ tệp. - Kích thước phân đoạn: đây là những "nguyên tử" dữ liệu nhỏ nhất cho ứng dụng của bạn. Bạn phải phân đoạn vì hiện có giới hạn kích thước gửi (mặc dù vấn đề này sẽ được khắc phục trong phiên bản kênh dữ liệu trong tương lai). Kích thước khối tối đa được đề xuất hiện tại là 64KiB.
Sau khi tệp được chuyển hoàn toàn sang phía bên kia, bạn có thể tải tệp đó xuống bằng thẻ neo:
function saveFile(blob) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'File Name';
link.click();
};
Các ứng dụng chia sẻ tệp này trên PubShare và GitHub sử dụng kỹ thuật này. Cả hai đều là nguồn mở và cung cấp nền tảng tốt cho ứng dụng chia sẻ tệp dựa trên RTCDataChannel
.
Vậy bạn có thể làm gì?
RTCDataChannel
mở ra những cách mới để xây dựng ứng dụng chia sẻ tệp, chơi trò chơi nhiều người chơi và phân phối nội dung.
- Hoạt động chia sẻ tệp ngang hàng như mô tả trước đó
- Chơi trò chơi nhiều người chơi, kết hợp với các công nghệ khác, chẳng hạn như WebGL, như trong BananaBread của Mozilla
- Phân phối nội dung do PeerCDN tái tạo, một khung phân phối tài sản web thông qua giao tiếp dữ liệu ngang hàng
Thay đổi cách bạn xây dựng ứng dụng
Giờ đây, bạn có thể cung cấp các ứng dụng hấp dẫn hơn bằng cách sử dụng các kết nối có hiệu suất cao, độ trễ thấp thông qua RTCDataChannel
. Các khung, chẳng hạn như PeerJS và SDK WebRTC PubNub, giúp triển khai RTCDataChannel
dễ dàng hơn và API hiện được hỗ trợ rộng rãi trên các nền tảng.
Sự xuất hiện của RTCDataChannel
có thể thay đổi cách bạn nghĩ về việc chuyển dữ liệu trong trình duyệt.