基于 WebRTC+WebSocket 的在线监考系统实现方案(附完整前后前端 + 后端完整代码)

88 阅读2分钟

在远程考试场景中,实时监控和双向通信是确保考试公平性的核心需求。本文将分享一个基于 WebRTC 和 WebSocket 技术的在线监考系统实现方案,包含前端学生端、监考端及后端服务代码,实现了视频监控、实时消息、作弊标记等核心功能。基本无任何延迟,经过改造以及二次开发后可做视频会议等应用。

系统架构设计

该系统采用 "前端实时通信 + 后端信令转发" 的架构:

  • 前端:使用 WebRTC 实现点对点视频流传输,WebSocket 处理信令交换和消息通信
  • 后端:基于 Spring Boot 实现 WebSocket 服务,负责会话管理、信令转发和学生状态维护
  • 核心技术:WebRTC(实时音视频)、WebSocket(长连接通信)、Spring Boot(后端服务)
核心功能实现
  1. 实时视频监控

    • 学生端通过getUserMedia获取摄像头 / 麦克风流,通过 WebRTC 推送到监考端

    • 监考端支持多宫格显示,可对单个视频进行全屏、声音控制和重新连接操作

    • 代码关键点:

      javascript

      运行

      localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
      
      function createStudentVideo(student) {
      
        const video = document.createElement('video');
      
  2. 分级消息通信

    • 支持三类消息发送:全体学生、指定年级、指定班级

    • 消息记录实时展示,包含时间戳和发送对象

    • 代码关键点:

      javascript

      运行

        const target = document.getElementById('targetSelect').value;
      
        ws.send(JSON.stringify({
      
          type: 'INVIGILATOR_MSG',
      
          to: target,  // 支持ALL/GRADE_x/CLASS_x_x
      
  3. 作弊标记与警告

    • 监考端可标记学生作弊并填写原因

    • 学生端实时收到作弊警告提示

    • 代码关键点:

      javascript

      运行

      function markCheat(studentId) {
      
        const reason = prompt(`请输入标记原因:`);
      
        ws.send(JSON.stringify({
      
          studentId: studentId,
      
      if (data.type === 'CHEAT_MARK') {
      
        alert(`警告:您已被标记为作弊!原因:${data.content}`);
      
  4. WebRTC 信令交互

    • 采用标准 SDP 协商流程(OFFER-ANSWER)

    • 使用 STUN 服务器进行 NAT 穿透

    • 后端负责信令转发,支持会话容错处理

    • 代码关键点:

      javascript

      运行

      const pc = new RTCPeerConnection({
      
        iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
      
      pc.onicecandidate = (event) => {
      
            type: 'ICE_CANDIDATE',
      
            data: event.candidate
      
后端核心逻辑
  1. WebSocket 会话管理

    • 维护学生和监考端的在线状态

    • 按考试 ID、年级、班级分组管理学生

    • 代码关键点:

      java

      运行

      public void addStudent(StudentInfo student) {
      
        onlineStudents.put(student.getStudentId(), student);
      
        String groupKey = getGroupKey(student.getInvigilateId(), student.getGradeId(), student.getClassId());
      
        studentGroupMap.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(student);
      
  2. 信令转发服务

    • 处理 WebRTC 信令(OFFER/ANSWER/ICE_CANDIDATE)的转发

    • 实现容错机制,确保信令可靠送达

    • 代码关键点:

      java

      运行

      private void forwardSignaling(SignalingData signaling) throws IOException {
      
        WebSocketSession targetSession = findSessionById(signaling.getTo());
      
        if (targetSession != null) {
      
          sendToSession(targetSession, signaling);
      

本文使用 文章同步助手 同步