+
95
-

回答

800_auto

发送文件我们先实现p2p发送消息,我们用php swoole搭建一个信令服务器

<?php

$userlist = [];
$server = new Swoole\Websocket\Server("0.0.0.0", 9502, SWOOLE_BASE, SWOOLE_SOCK_TCP | SWOOLE_SSL);

$server->set([
    'ssl_cert_file' => '/data/cert/6284283_web.debug.only.bfw.wiki.pem',
    'ssl_key_file' => '/data/cert/6284283_web.debug.only.bfw.wiki.key',

]);


$server->on('open', function($server, $req) {
    $_get = $req->get;
    $_username = $_get['username'];
    global $userlist;
    $userlist[$_username] = $req->fd;
    echo "connection open: {$req->fd}{$_username}\n";
});

$server->on('message', function($server, $frame) {

    $data = json_decode($frame->data, true);


    //消息类型
    $type = $data["type"];
    $_ret = ["type" => $type];

    //to user
    $toUser = $data["toUser"];

    $fromUser = $data["fromUser"];

    $msg = isset($data["msg"])?$data["msg"]:"";
    //msg

    $sdp = isset($data["sdp"])?$data["sdp"]:"";
    //sdp
    $iceCandidate = isset($data["iceCandidate"])?$data["iceCandidate"]:"";
    //ice




    //对方挂断
    if ("hangup" == $type) {
        $_ret['fromUser'] = $fromUser;
        $_ret['msg'] = "对方挂断";

    }

    //视频通话请求
    if ("call_start" == $type) {

        $_ret['fromUser'] = $fromUser;
        $_ret['msg'] = "1";

    }

    //视频通话请求回应
    if ("call_back" == $type) {
        $_ret['fromUser'] = $fromUser;
        $_ret['msg'] = $msg;

    }

    //offer
    if ("offer" == $type) {

        $_ret['fromUser'] = $toUser;
        $_ret['sdp'] = $sdp;

    }

    //answer
    if ("answer" == $type) {
        $_ret['fromUser'] = $toUser;
        $_ret['sdp'] = $sdp;

    }

    //ice
    if ("_ice" == $type) {
        $_ret['fromUser'] = $toUser;
        $_ret['iceCandidate'] = $iceCandidate;

    }
    if ($toUser != "") {
        global $userlist;
        if (!isset($userlist[$toUser])) {
            $_ret['msg'] = "Sorry,呼叫的用户不在线!";
            $_ret['type'] = "call_back";
            $_ret['fromUser'] = "系统消息";


            $_senddata = json_encode($_ret);
            $server->push($frame->fd, $_senddata);
        } else {
            foreach ($userlist as $key => $val) {
                if ($key == $toUser) {
                    $_senddata = json_encode($_ret);
                    echo "send message: {$_senddata}\n";
                    $server->push($val, $_senddata);
                }
            }
        }


    }

    // echo "received message: {$frame->data}\n";

});

$server->on('close', function($server, $fd) {
    echo "connection close: {$fd}\n";
});

$server->start();

在使用html实现

点击查看全文

<!DOCTYPE html>

<head>
    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
    <style>

    </style>
</head>

<body>
    <div id="main">
    <div id="messhis">
        
        
    </div>
        <div id="buttons">
            <span id="yourno"></span>
            
            
            <input id="toUser" placeholder="输入在线好友账号" /><br/>
            
            <textarea id="message">你好</textarea>
            <button id="connect">链接</button>
            
            <button id="send">发送</button>
        </div>
    </div>


    <script type="text/javascript" >
    var icecanarr=[];
    var dataChannel=null;
        let username = randomString(6);
        document.getElementById('yourno').innerHTML="您的账户名是:"+username;
        
        let localVideo = document.getElementById('localVideo');
        let remoteVideo = document.getElementById('remoteVideo');
        let websocket = null;
        let peer = null;
     
    
        WebSocketInit();
        ButtonFunInit();
    
    function randomString(len) {
      len = len || 32;
      var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
      var maxPos = $chars.length;
      var pwd = '';
      for (i = 0; i < len; i++) {
        pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
      }
      return pwd;
    }
    
    
        /* WebSocket */
        function WebSocketInit(){
            //判断当前浏览器是否支持WebSocket
            if ('WebSocket' in window) {
                websocket = new WebSocket("wss:/web.debug.only.bfw.wiki:9502/?username="+username);
            } else {
                alert("当前浏览器不支持WebSocket!");
            }
    
            //连接发生错误的回调方法
            websocket.onerror = function (e) {
                alert("WebSocket连接发生错误!");
            };
    
            //连接关闭的回调方法
            websocket.onclose = function () {
                console.error("WebSocket连接关闭");
            };
    
            //连接成功建立的回调方法
            websocket.onopen = function () {
                console.log("WebSocket连接成功");
            };
    
            //接收到消息的回调方法
            websocket.onmessage = async function (event) {
              let { type, fromUser, msg, sdp, iceCandidate } = JSON.parse(event.data.replace(/\n/g,"\\n").replace(/\r/g,"\\r"));


                console.log(type);
                
               

    
                if (type === 'hangup') {
                    console.log(msg);
                    document.getElementById('hangup').click();
                    return;
                }
    
                if (type === 'call_start') {
                    let msg = "0"
                   
                        document.getElementById('toUser').value = fromUser;
                        WebRTCInit();
                         
                        msg = "1"
                  
    
                    websocket.send(JSON.stringify({
                        type:"call_back",
                        toUser:fromUser,
                        fromUser:username,
                        msg:msg
                    }));
    
                    return;
                }
    
                if (type === 'call_back') {
                    if(msg === "1"){
                       
    
                      
    
                        let offer = await peer.createOffer();
                        await peer.setLocalDescription(offer);
    
                        let newOffer = offer.toJSON();
                        newOffer["fromUser"] = username;
                        newOffer["toUser"] = document.getElementById('toUser').value;
                        websocket.send(JSON.stringify(newOffer));
                    }else if(msg === "0"){
                        alert(document.getElementById('toUser').value + "拒绝视频通话");
                        document.getElementById('hangup').click();
                    }else{
                        alert(msg);
                        document.getElementById('hangup').click();
                    }
    
                    return;
                }
    
                if (type === 'offer') {
                   
    
                    await peer.setRemoteDescription(new RTCSessionDescription({ type, sdp }));
                     for (let i = 0; i < icecanarr.length; i++) {
                         peer.addIceCandidate(icecanarr[i]);
 
                     }
                    console.log(peer.remoteDescription)
                    let answer = await peer.createAnswer();
                    let newAnswer = answer.toJSON();
    
                    newAnswer["fromUser"] = username;
                    newAnswer["toUser"] = document.getElementById('toUser').value;
                    websocket.send(JSON.stringify(newAnswer));
    
                    await peer.setLocalDescription(answer);
                    // 创建数据通道

                     //ice
           
    
                    return;
                }
    
                if (type === 'answer') {
                       console.log(type)
                    console.log(sdp)
                    
                   
                    peer.setRemoteDescription(new RTCSessionDescription({ type, sdp }));
                    for (let i = 0; i < icecanarr.length; i++) {
                         peer.addIceCandidate(icecanarr[i]);
 
                     }
                     
                     
                  
                    return;
                }
    
                if (type === '_ice') {
                  if(peer.remoteDescription!=null){
                      peer.addIceCandidate(iceCandidate);
                  }else{
                      icecanarr.push(iceCandidate);
                  }


                    // console.log(iceCandidate);
                    // peer.addIceCandidate(iceCandidate);
                    return;
                }
    
            }
        }
    
        /* WebRTC */
        function WebRTCInit(){
            
            const config = {
 'iceServers': [
        {
            'url': 'stun:web.debug.only.bfw.wiki:3478',
        },
        {
            'url': 'turn:web.debug.only.bfw.wiki:3478',
            'username': 'bfw',
            'credential': 'bfw'
        }
    ]
};


            peer = new RTCPeerConnection(config);
            
            
               dataChannel = peer.createDataChannel("textChannel");

// 监听数据通道的打开事件
dataChannel.onopen = () => {
  console.log("数据通道已打开发送消息");
  // 可以开始发送文本消息
   dataChannel.send("Hello, P2P!");

};

// 监听数据通道的错误事件
dataChannel.onerror = (error) => {
  console.error("数据通道错误:", error);
};

// 监听数据通道的关闭事件
dataChannel.onclose = () => {
  console.log("数据通道已关闭");
};

// 监听接收到的文本消息
dataChannel.onmessage = (event) => {
  const receivedMessage = event.data;
    appendmess(receivedMessage)
  console.log("接收到的消息:", receivedMessage);
};
                              //track
           // 监听数据通道的消息事件
peer.ondatachannel = (event) => {
  const recdataChannel = event.channel;

  // 监听数据通道的打开事件
  recdataChannel.onopen = () => {
    console.log("数据通道已打开");
  };

  // 监听数据通道的错误事件
  recdataChannel.onerror = (error) => {
    console.error("数据通道错误:", error);
  };

  // 监听数据通道的关闭事件
  recdataChannel.onclose = () => {
    console.log("数据通道已关闭");
  };

  // 监听接收到的文本消息
  recdataChannel.onmessage = (event) => {
    const receivedMessage = event.data;
       appendmess(receivedMessage)
    console.log("接收到的消息:", receivedMessage);
  };
}; 
     peer.onicecandidate = function (e) {
                if (e.candidate) {
                    
   websocket.send(JSON.stringify({
                        type: '_ice',
                        toUser:document.getElementById('toUser').value,
                        fromUser:username,
                        iceCandidate: e.candidate
                    }));

                }
              
            };
           
         
        }
        
        



        /* 按钮事件 */
        function ButtonFunInit(){
            //链接
            document.getElementById('connect').onclick = function (e){
                document.getElementById('toUser').style.visibility = 'hidden';
    
                let toUser = document.getElementById('toUser').value;
                if(!toUser){
                    alert("请先指定好友账号,再发送消息!");
                    return;
                }
    
                if(peer == null){
                    WebRTCInit();
                }
    
                websocket.send(JSON.stringify({
                    type:"call_start",
                    fromUser:username,
                    toUser:toUser,
                }));
            }
    
            //发送
            document.getElementById('send').onclick = function (e){
              let mess = document.getElementById('message').value;
     dataChannel.send(mess);
    
     appendmess(mess)
               
            }
        }
        
        function appendmess(mess){
            
   var listItem = document.createElement("li");

// 设置 <li> 元素的文本内容
listItem.textContent = mess;

 document.getElementById('messhis').appendChild(listItem);
        }
    </script>
</body>

</html>

网友回复

我知道答案,我要回答