Tóm tắt

Hẳn là các bạn cũng nhận ra được một vài ứng dụng quen thuộc ở hình phía trên. Các ứng dụng này đều là những ứng dụng cho phép chúng ta có một cuộc hội thoại thời gian thực. Và thật hấp dẫn khi biết rằng chúng sử dụng công nghệ WebRTC để thực hiện được việc đó.

Ở ngay trang chủ WebRTC không khó để chúng ta nhận ra rằng công nghệ này được hỗ trợ mạnh mẽ bởi những team công nghệ hàng đầu Apple, Google, Microsoft and Mozilla và đặc biệt là Google. Có thể nói, ngày nay WebRTC là một công nghệ rất tuyệt vời đề cho phép chúng ta xây dựng được cuộc hội thoại thời gian thực. Bao gồm những ưu điểm như độ trễ thấp, và an toàn.

Tại blog.vietnamlab.vn chúng tôi cũng đã có một bài viết về việc tìm hiểu webRTC đề cập đến các thành phần của WebRTC và các biểu đồ cho thấy sự hấp dẫn và phát triển mạnh mẽ của WebRTC gần đây, đặc biệt trong giai đoạn mà thế giới đương đầu với đại dịch Covid, việc trao đổi thông tin từ xa trở nên vô cùng quan trọng. Bài viết nay sẽ đi vào chi tiết hơn về "Discovery and Negotiation mechanism" chúng ta có thể hiểu là cơ chế khám phá và đàm phán của WebRTC.

Mở đầu

Chúng ta đã biết WebRTC là một công nghệ tuyệt vời cho phép chúng ta thực hiện những cuộc hội thoại thời gian thực. Nhìn bề ngoài, có thể thấy chúng ta không cần gì ngoài một trình duyệt và một kết nối ổn định để thực hiện một cuộc hội thoại thông qua WebRTC. Tuy nhiên, dưới bề ngoài đó, là một hệ thống máy chủ Signaling server mà các nhà phát triển cần để được có thông tin điều hướng cho việc chuyển tiếp các gói tin ngang hàng với nhau.

1.Signaling servers là gì?

Trong thực tế, các kết nối của chúng ta ra ngoài Internet đề đi qua rất nhiều trở ngại như tường lửa, các router Nat. Vì vậy, ngay cả khi được xây dựng dựa trên giao thức P2P nhưng các ứng dụng WebRTC không thể hoạt động nếu không có loại server này. Để cho 2 thiết bị có thể định vị được nhau cần có cớ chế khám phá và đàm phán diễn ra. Chúng ta có thể gọi hành vi này là Signaling.

Peer Connection Problem
Peer Connection Problem

Tuy nhiên, WebRTC API không cung cấp các giải pháp nào để thực hiện quy trình này nên các nhà phát triển cần thiết lập một khuôn khổ cho phép WebRTC khắc phục sự phức tạp của giao tiếp thời gian thực, cũng chính là nói đến việc thiết lập các Signaling server.

2.STUN Server

Việc trao đổi thông tin liên lạc theo thời gian thực (video, âm thanh, chia sẻ màn hình và dữ liệu khác) yêu cầu các thiết bị kết nối với máy chủ được hai bên thống nhất. Các máy chủ STUN (Session Traversal Utilities for NAT)TURN(Traversal Using Relays around NAT) đều được sử dụng trong quá trình Signaling nhưng vì những lý do khác nhau thì sẽ sử dụng trong những tình huống khác nhau.

Trước khi thiết lập kết nối ngang hàng, điều cần thiết là máy chủ phải xác định địa chỉ IP của từng người tham gia. Các ứng dụng WebRTC hầu hết sử dụng máy chủ STUN. Phương pháp này đơn giản, nhanh chóng và quan trọng nhất là chúng không tốn nhiều tài nguyên mạng.

Stun Server
Stun Server

STUN Server là một máy chủ hoạt động theo giao thức STUN. Nhiệm vụ của STUN Server là cung cấp thông tin về địa chỉ IP và cổng của máy tính client từ gói tin STUN Request.

Cơ chế hoạt động

  • Khi máy tính client muốn biết địa chỉ IP và cổng của nó từ gói tin STUN Request, nó gửi một yêu cầu STUN Request đến STUN Server.
  • STUN Server nhận yêu cầu và phản hồi bằng một gói tin STUN Response.
  • Gói tin STUN Response chứa thông tin về địa chỉ IP và cổng của máy tính client, sau khi nó đã được thay đổi bởi NAT (nếu có).
  • Máy tính client sử dụng thông tin này để xác định cách kết nối trực tiếp với máy tính khác, bằng cách chia sẻ thông tin này với máy tính khác thông qua một kênh trung gian (chẳng hạn như một máy chủ trung gian hoặc một giao thức khác như TURN, hoặc thông qua một  web Socket).

Thêm vào đó, khi phiên đã được thiết lập, các media sẽ được trao đổi trực tiếp giữa những người tham gia. Tuy nhiên, STUN đôi khi bị hạn chế bởi tường lửa. Vì vậy, các nhà phát triển cần chuyển sang và sử dụng máy chủ TURN khi STUN bị lỗi.

3. TURN Server

Firewall và môi trường khép kín như mạng nội bộ công ty có thể hạn chế quyền truy cập vào địa chỉ IP. Nếu không có một dấu hiệu nhận biết duy nhất, hai mạng sẽ không thể tìm thấy nhau. Vấn đề này có thể được giải quyết bằng cách sử dụng máy chủ TURN làm  trung gian. Không giống như STUN, máy chủ TURN vẫn nằm trong kênh truyền media sau khi kết nối được thiết lập.

Turn Server
Turn Server

TURN Server là máy chủ hoạt động theo giao thức TURN. Nhiệm vụ của TURN Server là chấp nhận dữ liệu từ máy tính client, chuyển tiếp nó và gửi nó đến máy tính khác thông qua Internet.

Cơ chế hoạt động

  • Khi máy tính client không thể thiết lập kết nối trực tiếp với máy tính khác (do NAT hoặc Firewall), nó sẽ thực hiện một yêu cầu kết nối đến TURN Server.
  • TURN Server sẽ đón nhận yêu cầu và sẽ trở thành máy chủ trung gian cho việc truyền dữ liệu giữa máy tính client và máy tính khác.
  • Máy tính client sau đó gửi dữ liệu của mình đến TURN Server.
  • TURN Server chuyển tiếp dữ liệu này đến máy tính đích thông qua Internet, vượt qua NAT và Firewall mà máy tính client không thể tránh được.
  • Máy tính đích nhận dữ liệu từ TURN Server và có thể gửi phản hồi trở lại thông qua cùng một kênh.

Điểm quan trọng cần lưu ý

  • TURN Server là một máy chủ trung gian, và việc chuyển tiếp dữ liệu thông qua nó có thể tạo ra một mức độ trễ và tăng lưu lượng mạng.
  • TURN thường được sử dụng khi các giải pháp khác như STUN không hoạt động hoặc không đủ để thiết lập kết nối trực tiếp.

Cơ chế này cho phép máy tính client và máy tính đích truyền dữ liệu qua Internet, mặc dù họ có thể nằm sau các thiết bị NAT hoặc Firewall gây khó khăn cho việc thiết lập kết nối trực tiếp.

Trên hết, nó cũng có thể làm tăng chi phí vận hành cơ sở hạ tầng của bạn. Bạn càng hướng nhiều lưu lượng truy cập đến máy chủ TURN của mình thì bạn càng cần tốn nhiều chi phí cho cơ sở hạ tầng.

4. ICE Protocol

ICE (Interactive Connectivity Establishment) là một trong những phần quan trọng nhất của công nghệ WebRTC và có vai trò quan trọng trong việc thiết lập kết nối trực tiếp giữa các máy tính và thiết bị trong mạng Internet, đặc biệt khi máy tính này nằm sau các thiết bị NAT (Network Address Translation) và Firewall.

Cơ chế hoạt động

  • Máy tính Client và Đích sẽ sử dụng giao thức ICE để xác định cách thiết lập kết nối trực tiếp. ICE sử dụng hai phần chính: STUN và TURN.
  • STUN (Optional): Nếu STUN Server được sử dụng, máy tính Client sẽ gửi yêu cầu STUN để lấy địa chỉ IP và cổng bên ngoài của mình. Điều này giúp xác định cách kết nối với máy tính Đích mà không cần TURN.
  • TURN (Optional): Nếu truyền dữ liệu trực tiếp qua NAT hoặc Firewall không thành công (ví dụ: do NAT không hỗ trợ UPnP hoặc NAT-PMP), máy tính Client sẽ sử dụng TURN Server làm máy chủ trung gian để chuyển tiếp dữ liệu giữa hai máy tính. Điều này đảm bảo rằng kết nối có thể thiết lập mặc dù các rào cản của NAT và Firewall.

ICE cho phép máy tính Client và Đích thử nghiệm và chọn cách kết nối tốt nhất để truyền dữ liệu giữa họ. Điều này giúp đảm bảo tính ổn định và chất lượng của kết nối trong các ứng dụng WebRTC, chẳng hạn như cuộc gọi video và trò chuyện trực tiếp qua Internet.

5. Giới thiệu Metered.ca WebRTC Api Provider

Kể từ đợt dịch COVID, rất nhiều đơn vị cung cấp các giải pháp API cho WebRTC, giúp chúng ta đơn giản hóa việc tạo các STUN và TURN server tùy theo nhu cầu sử dụng.

Trong đó thì mình cũng đã sử dụng dịch vụ bên Metered.ca. Ngay khi đăng ký tài khoản thì chúng ta được cấp user/password cho dịch vụ TURN server và được 1 lượng lưu lượng miễn phí. Ngoài ra thì miễn phí dịch vụ STUN server. Các bạn cũng có thể thử để tạo ứng dụng WEBRTC

Ngoài ra, dịch vụ bên Metered này cung cấp các API để phát triển các ứng dụng hội thoại 1:1 hoặc group meeting giúp đơn giản hóa việc phát triển các ứng dụng.

6. Setup ứng dụng chia sẻ file peer-2-peer đơn giản bằng WebRTC

Chúng ta có thể tạo một ứng dụng đơn giản chia sẻ file  đề làm quen cách hoạt động của WebRTC bao gồm

  • Tạo Data Channel
  • Trao đổi SPD, Candidates và thực hiện kết  nối 2 peers
  • Trao đổi 1 tệp tin

Github: info-namnt/webrtc-tranferfile: Demo Webrtc tranferfile (github.com)

Mình cũng đã tạo sẵn 1 demo source các quí bạn đọc giả có thể tham khảo qua

Điều thuận tiện là các browser hiện nay đều hỗ trợ các API WebRTC nên khi phát triển một ứng dụng không cần cài đặt thêm dependencies nào

Bạn có thể bắt đầu tạo ứng dụng bằng việc tạo một ứng dụng Nodejs, riêng mình thì mình sử dụng Nuxt Framework.

Bước 1: Bạn có thể tạo 1 project riêng của mình bằng lệnh sau

npx nuxi@latest init

Bước 2: Chuẩn bị các server STUN/ TURN bằng Metered.ca . Sau khi bạn đăng ký tài khoản thì bạn sẽ được cấp 1 lượng lưu lượng miễn phí sử dụng các server STUN/ TURN mà Metered cung cấp.

Bước 3: Tạo ra đối tượng RTCPeerConnection, đối tượng này đại diện cho 1 peers và các action này đại diện cho các giao tiếp của WebRTC

const configuration = {
        iceServers: [
           {
            urls: ["stun:stun.relay.metered.ca:80"],
           },
          {
              urls: "turn:a.relay.metered.ca:80",
              username: "535d4b330b8133f51bba857a",
              credential: "***n/d*********",
          }...
        ]
      };
  
    peerConnection = new RTCPeerConnection(configuration);

Bước 4: Tạo luồng truyền dữ liệu, còn gọi là DataChannel

   dataChannel = peerConnection.createDataChannel('fileTransfer');

Bước 5: Thực hiện Signaling đến STUN/ TURN server để lấy các thông tin ICE và SDP (khi thực hiện kết nối p2p, các Peers sẽ cần phải trao đổi các thông tin này với nhau

peerConnection.onicecandidate = (event) => {
      if (event.candidate) {
        candidates.push(event.candidate);
        jsonCandidates.value = JSON.stringify(candidates);
      }

      // Listen for connection state changes
      peerConnection.oniceconnectionstatechange = function() {
        console.log('ICE connection state change: ', peerConnection.value.iceConnectionState);
      };
    };

    const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(offer);
    sdp.value = JSON.stringify(peerConnection.localDescription);

Chúng ta có thể thấy được cấu trúc của ICE và SDP sau khi bấm button "Create DataChannel" như sau, ICE Candidate chính là hướng dẫn 1 peer khác có thể kết nối đến peer mà bạn đang mở. SDP là mô tả các kết nối bao gồm các giao thức, mã hóa ...

Bước 6: Tiến hành kết nối Peer2 với Peer1 bằng cách trao đổi các thông tin SDP và ICE Candidates với nhau

await peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(remoteSdp.value)));
    const answer = await peerConnection.createAnswer();
    await peerConnection.setLocalDescription(answer);
    const candidatesArray = JSON.parse(remoteJsonCandidates.value);
    for (const candidate of candidatesArray) {
      await peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
    }

Trên đây mình đã tóm tắt các bước để 2 peers có thể bắt đầu kết nối với nhau

Về việc trao đổi media với nhau các quí bạn đọc có thể tham khảo link github mình đã ghi chú lại từ đầu phần 6

7. Kết luận


Giao tiếp video thời gian thực đi kèm với một loạt thách thức. Ngay cả khi WebRTC được thiết kế để hoạt động ngang hàng thì nó vẫn yêu cầu xây dựng toàn bộ kiến trúc tín hiệu đằng sau nó. Điều này có nghĩa là việc mở rộng quy mô đòi hỏi phải đầu tư thêm vào cơ sở hạ tầng máy chủ.

8. Tham khảo

9. Trải nghiệm khi xây dựng ứng dụng trên công nghệ WebRTC

  • Trên thực tế các ứng dụng WebRTC cần phải có 1 kênh broadcast thông tin và quản lý phòng riêng (vd: bạn có thể sử dụng socket.io hoặc redis).
  • Các kết nối của WebRTC là 1-1, vì vậy khi thực hiện kết nối n-n mỗi peers sẽ cần kết nối với n-1 peers khác (ví dụ bạn có hội thoại 4 người thì sẽ có 4*3 kết nối ). Vấn đề này có thể làm các ứng dụng ngốn tài nguyên của thiết bị khi nhiều người dùng cùng tham gia hội thoại hơn (tương tự như các cuộc gọi trên zoom, fb khi nhiều người tham gia bạn cảm thấy máy nóng và chạy chậm hơn).
  • Bạn cũng có thể phát triển các ứng dụng streaming  (1-n) thông qua các việc xây dựng server truyền kênh Data riêng.
  • Nhìn chung có rất nhiều bài toán ứng dụng WebRTC và cũng có nhiều bài toán phát sinh từ việc sử dụng WebRTC tuy nhiên luôn sẽ có giải pháp mà bạn cần.

Hy vọng bài viết này sẽ giúp các bạn đọc giả dễ dàng tiếp cận với WebRTC và xây dựng ứng dụng của riêng mình