WebRTC仅局域网可用排查:React Hook+Socket.io跨网连接失败
WebRTC跨网连接失败排查方案
一、先确认TURN服务器真的能用
别光换TURN服务器,先验证配置是否生效:
- 用浏览器控制台跑这段代码,检查能不能拿到
relay类型的ICE候选:
如果控制台没输出const iceConfig = { iceServers: [ { urls: 'stun:stun.l.google.com:19302' }, { urls: 'turn:你的TURN服务器地址:端口', username: '你的用户名', credential: '你的密码' } ] }; const pc = new RTCPeerConnection(iceConfig); pc.onicecandidate = e => { if (e.candidate) console.log('ICE候选类型:', e.candidate.type, '地址:', e.candidate.address); }; pc.createDataChannel('test-channel'); pc.createOffer().then(offer => pc.setLocalDescription(offer));relay类型的候选,说明TURN配置肯定有问题——要么端口没开放(TURN默认3478/UDP,还要确认TCP端口是否开启),要么用户名密码错了,要么服务器本身没正常运行。 - 必须同时配置STUN和TURN,别只配TURN,STUN用来获取公网地址,TURN用来中继流量。
二、检查Socket.io信令服务的跨网支持
- 确保Next.js的Socket.io服务端开了跨域:
const io = require('socket.io')(server, { cors: { origin: "*", // 生产环境改成具体的前端域名,别用通配符 methods: ["GET", "POST"] } }); - 加日志确认信令消息没丢:
在客户端发offer、answer、iceCandidate的时候,服务端也打日志,检查消息的sdp、sdpMid、sdpMLineIndex这些关键字段是不是完整传递了——这些字段缺一个都可能导致ICE配对失败。
三、WebRTC Hook逻辑的常见坑
- 严格按流程调用API:
别在createOffer之后直接发消息,要等本地描述设置完成再发:// 正确写法 const offer = await pc.createOffer(); await pc.setLocalDescription(offer); socket.emit('offer', offer); // 这时候再发offer - 处理ICE候选别偷懒:
收到对方的ICE候选时,一定要等pc.remoteDescription已经设置好了再调用addIceCandidate,而且所有候选都要加,别过滤局域网地址——WebRTC自己会筛选能用的。 - 别提前关闭候选收集:
一定要等onicecandidate回调收到null候选(表示收集完了)再停止发送,不然可能漏掉关键的relay候选。
四、从日志里找线索
看WebRTC日志的时候重点抓这些关键词:
ICE failed, add a STUN server:STUN/TURN完全没生效,连公网候选都拿不到No candidates found for pair:双方没有能配对的候选,大概率是TURN没起作用Connection failed:往前翻日志,看是ICE收集阶段报错,还是信令消息没收到
五、其他小细节
- 检查浏览器权限:确保摄像头、麦克风权限开了,有些浏览器会因为权限问题阻断WebRTC连接
- 换网络测试:比如用手机4G连,排除本地网络的NAT类型问题(对称NAT必须用TURN才能穿透)
内容的提问来源于stack exchange,提问作者celestrogen
相关产品推荐
相关产品推荐

