发送文件我们先实现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>
网友回复