webRTC(十八):webrtc 实现web端对端的纯文本聊天互通

  • 效果

在这里插入图片描述

端对端的纯文本聊天互通,是在webRTC(十四):webrtc 端到端文本聊天基础上,将音视频信息去除以后得到的结果。
具体代码如下

  • html
<html>
	<head>
		<title>WebRTC PeerConnection</title>
		<style>
			.preview{
				display: flex;
			}
			.remote{
				margin-left: 20px;
			}
			.text_chat{
				display: flex;
			}
			.text_chat textarea{
				width: 350px;
				height: 350px;
			}
			.send{
				margin-top: 20px;
			}
		</style>
	</head>
	<body>
		<div>
			<div>
				<button id="connserver">Connect Sig Server</button>
				<button id="leave" disabled>Leave</button>
			</div>
			<!--文本聊天-->
			<h2>Chat:</h2>
			<div class="text_chat">
				<div>
					<textarea id="chat" disabled></textarea>
				</div>
				<div class="remote">
					<textarea id="sendtext" disabled></textarea>
				</div>
			</div>
			<div class="send">
				<button id="send" disabled>Send</button>
			</div>
		</div>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
		<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
		<script src="./js/client.js"></script>
	</body>
</html>
  • js
'use strict'

var btnConn = document.querySelector('button#connserver');
var btnLeave = document.querySelector('button#leave');

// 文本聊天
var chat = document.querySelector('textarea#chat');
var send_txt = document.querySelector('textarea#sendtext');
var btnSend = document.querySelector('button#send');

var roomid = '888888';
var socket =null;

var state = 'init';

var pc = null;
var dc = null;

var pcConfig={
		'iceServers':[{
			'urls':'turn:121.41.76.43:3478',
			'credential':'123456',
			'username':'huang'
		}]
	}

function sendMessage(roomid,data){
	if(socket){
		socket.emit('message',roomid,data);
	}
}

function getAnswer(desc){
	pc.setLocalDescription(desc);
	sendMessage(roomid,desc);
}

function handleAnswerError(err){
	console.error('Failed to get Answer!',err);
}

function getOffer(desc){
	pc.setLocalDescription(desc);
	sendMessage(roomid,desc)
}
function handleOfferError(err){
	console.error('Failed to get Offer!',err);
}

//接收远端流通道
function call(){
	if(state === 'joined_conn'){
		if(pc){
			var options = {
				offerToReceiveAudio:1,
				offerToReceiveVideo:1
			}
			pc.createOffer(options)
			  .then(getOffer)
			  .catch(handleOfferError);
		}
	}	
}
// 第一步:开始服务
function connSignalServer(){
	conn();
	return true;
}

//文本对方传过来的数据
function reveivemsg(e){
	var msg = e.data;
	if(msg){
		chat.value += '->' + msg + '\r\n';
	}else{
		console.error('recreived msg is null');
	}
}

function dataChannelStateChange(){
	var readyState=dc.readyState;
	if(readyState==='open'){
		send_txt.disabled =false;
		btnSend.disabled=false;
	}else{
		send_txt.disabled = true;
		btnSend.disabled =true;
	}
}


function conn(){
	//1 触发socke连接
	socket = io.connect();
	
	//2 加入房间后的回调
	socket.on('joined',(roomid,id)=>{
		
		state = 'joined';
		
		createPeerConnection();
		
		btnConn.disabled = true;
		btnLeave.disabled =false;
		
		console.log("reveive joined message:state=",state);	
	});
	socket.on('otherjoin',(roomid,id)=>{
		
		if (state === 'joined_unbind') {
			createPeerConnection();
		}
		
		//文本聊天
		// dc=pc.createDataChannel('chatchannel');
		var dataChannelOptions = {
		  ordered: true, //保证到达顺序
		};
		dc=pc.createDataChannel('dataChannel',dataChannelOptions);
		dc.onmessage=reveivemsg;
		dc.onopen = dataChannelStateChange;
		dc.onclose = dataChannelStateChange;
		
		
		state = 'joined_conn';
		
		//媒体协商
		call();
		console.log("reveive otherjoin message:state=",state);	
	});
	socket.on('full',(roomid,id)=>{
		console.log('receive full message ', roomid, id);

		closePeerConnection();
		
		state = 'leaved';
		
		btnConn.disabled = false;
		btnLeave.disabled = true;
		console.log("reveive full message:state=",state);
		alert("the room is full!");
	});
	
	socket.on('leaved',(roomid,id)=>{
		
		state = 'leaved';
		socket.disconnect();
		btnConn.disabled = false;
		btnLeave.disabled = true;
		console.log("reveive leaved message:state=",state);
	});
	
	socket.on('bye',(roomid,id)=>{
		
		state = 'joined_unbind';
		closePeerConnection();
		console.log("reveive bye message:state=",state);	
	});
	socket.on('disconnect', (socket) => {
		console.log('receive disconnect message!', roomid);
		if(!(state === 'leaved')){
			closePeerConnection();
		}
		state = 'leaved';
	
	});
	socket.on('message',(roomid,id,data)=>{
		console.log(" message=====>",data);
		//媒体协商
		if(data){
			if(data.type === 'offer'){
				pc.setRemoteDescription(new RTCSessionDescription(data));
				pc.createAnswer()
				  .then(getAnswer)
				  .catch(handleAnswerError);
			}else if(data.type === 'answer'){
				console.log("reveive client message=====>",data);
				pc.setRemoteDescription(new RTCSessionDescription(data));
			}else if(data.type === 'candidate'){
				var candidate = new RTCIceCandidate({
					sdpMLineIndex:data.label,
					candidate:data.candidate
				});
				pc.addIceCandidate(candidate);
				
			}else{
				console.error('the message is invalid!',data)
			}
		}
		
		console.log("reveive client message",roomid,id,data);	
	});
	
	socket.emit('join',roomid);
	return;
}




function leave(){
	if(socket){
		socket.emit('leave',roomid);
	}
	
	//释放资源
	closePeerConnection();
		
	btnConn.disabled = false;
	btnLeave.disabled = true;
}

//创建本地流媒体链接
function createPeerConnection(){
	console.log('create RTCPeerConnection!');
	if(!pc){
		pc = new RTCPeerConnection(pcConfig);
		pc.onicecandidate = (e) =>{
			if(e.candidate){
				sendMessage(roomid,{
					type:'candidate',
					label:e.candidate.sdpMLineIndex,
					id:e.candidate.sdpMid,
					candidate:e.candidate.candidate
				});
			}
		}
		
		//文本聊天
		pc.ondatachannel = e =>{
			// if(!dc){
				dc= e.channel;
				dc.onmessage =reveivemsg;
				dc.onopen = dataChannelStateChange;
				dc.onclose = dataChannelStateChange;
			// }
		}
		
		
	}
	if(pc === null || pc === undefined){
			console.error('pc is null or undefined!');
			return;
	}
}




//关闭本地媒体流链接
function closePeerConnection(){
	console.log('close RTCPeerConnection!');
	if(pc){
		pc.close();
		pc = null;
	}
}



//发送文本
function sendText(){
	var data = send_txt.value;
	if(data){
		dc.send(data);
	}
	send_txt.value="";
	chat.value += '<-' +data+'\r\n';
}


btnConn.onclick = connSignalServer;

btnLeave.onclick = leave;

btnSend.onclick=sendText;




测试地址:https://www.huangxiaoguo.club/onlyText/index.html

发布了316 篇原创文章 · 获赞 660 · 访问量 122万+

猜你喜欢

转载自blog.csdn.net/huangxiaoguo1/article/details/104230617