设为首页 收藏本站
查看: 911|回复: 0

[经验分享] webrtc学习笔记7(datachannel在jslinux的应用,nodejs版本)

[复制链接]

尚未签到

发表于 2017-2-22 10:14:38 | 显示全部楼层 |阅读模式
目标:
两个浏览器的jslinux可以进行数据交互
DSC0000.jpg
DSC0001.png
fabrice的jslinux是跑在浏览器中的linux,
提供了通过
/dev/clipboard 与<textare>交互的功能,交互的方法是clipboard_set
可以在jslinux.js中的clipboard_set方法中加入
datachannel的send方法,使两个浏览器中的textare有数据同步
从而是jslinux中通过一个linux的clipboard与另一个jslinux的clipboard交互
jslinux.js中修改的代码:

/*
Linux launcher
Copyright (c) 2011-2012 Fabrice Bellard
Redistribution or commercial use is prohibited without the author's
permission.
*/
"use strict";
var term, pc, boot_start_time, init_state;
function term_start()
{
term = new Term(80, 130, term_handler);
term.open();
}
/* send chars to the serial port */
function term_handler(str)
{
pc.serial.send_chars(str);
}
console.log("hao:version 1.2")
function clipboard_set(val)
{
console.log("hao:clipboard_set---sendData->");
var el;
el = document.getElementById("text_clipboard");
el.value = val;
sendData();
}
function clipboard_get()
{
console.log("hao:clipboard_get---->");
var el;
el = document.getElementById("text_clipboard");
return el.value;
}
function clear_clipboard()
{
var el;
el = document.getElementById("text_clipboard");
el.value = "";
}
/* just used to display the boot time in the VM */
function get_boot_time()
{
return (+new Date()) - boot_start_time;
}
function start()
{
var params;
init_state = new Object();
params = new Object();
/* serial output chars */
params.serial_write = term.write.bind(term);
/* memory size (in bytes) */
params.mem_size = 16 * 1024 * 1024;
/* clipboard I/O */
params.clipboard_get = clipboard_get;
params.clipboard_set = clipboard_set;
params.get_boot_time = get_boot_time;
/* IDE drive. The raw disk image is split into files of
* 'block_size' KB.
*/
params.hda = { url: "bin/hda%d.bin", block_size: 64, nb_blocks: 912 };
pc = new PCEmulator(params);
init_state.params = params;
//pc.load_binary("vmlinux-2.6.20.bin", 0x00100000, start2);
//pc.load_binary("vmlinux26.bin", 0x00100000, start2);
//    pc.load_binary("vmlinuxtest.bin", 0x00100000, start2);
//pc.load_binary("vmlinuxnono.bin", 0x00100000, start2);
//pc.load_binary("vmlinux319.bin", 0x00100000, start2);
pc.load_binary("vmlinux319clip.bin", 0x00100000, start2);
}
function start2(ret)
{
if (ret < 0)
return;
init_state.start_addr = 0x10000;
//pc.load_binary("linuxstartnew.bin", init_state.start_addr, start3);
pc.load_binary("linuxstart.bin", init_state.start_addr, start3);
}
function start3(ret)
{
var block_list;
if (ret < 0)
return;
/* Preload blocks so that the boot time does not depend on the
* time to load the required disk data (optional) */
block_list = [ 0, 7, 3, 643, 720, 256, 336, 644, 781, 387, 464, 475, 131, 589, 468, 472, 474, 776, 777, 778, 779, 465, 466, 473, 467, 469, 470, 512, 592, 471, 691, 697, 708, 792, 775, 769 ];
pc.ide0.drives[0].bs.preload(block_list, start4);
}
function start4(ret)
{
var cmdline_addr;
if (ret < 0)
return;
/* set the Linux kernel command line */
cmdline_addr = 0xf800;
pc.cpu.write_string(cmdline_addr, "console=ttyS0 root=/dev/hda ro init=/sbin/init notsc=1 hdb=none");
pc.cpu.eip = init_state.start_addr;
pc.cpu.regs[0] = init_state.params.mem_size; /* eax */
pc.cpu.regs[3] = 0; /* ebx = initrd_size (no longer used) */
pc.cpu.regs[1] = cmdline_addr; /* ecx */
boot_start_time = (+new Date());
pc.start();
}
term_start();


jslinux的html修改的代码:

<!DOCTYPE html>
<html>
<head>
<title>Javascript PC Emulator</title>
<style>
.term {
font-family: courier,fixed,swiss,monospace,sans-serif;
font-size: 14px;
color: #f0f0f0;
background: #000000;
}
.termReverse {
color: #000000;
background: #00ff00;
}
#note {
font-size: 12px;
}
#copyright {
font-size: 10px;
}
#clipboard {
font-size: 12px;
}
</style>
</head>
<body >
<table border="0">
<tr valign="top"><td>
<script type="text/javascript" src="jquery.js"></script>  
<script type="text/javascript" src="utils.js"></script>
<script type="text/javascript" src="term.js"></script>
<script type="text/javascript" src="cpux86.js"></script>
<script type="text/javascript" src="jslinux.js"></script>

<div id="copyright">&copy; 2011 Fabrice Bellard - <a href="news.html">News</a> - <a href="faq.html">FAQ</a> - <a href="tech.html">Technical notes</a></div>
<input type="button" value="Clear clipboard" ><br><textarea row="4" cols="16" id="text_clipboard" ></textarea></br>
<input type="button" value="addletter" >
<input type="button" value="start" >

</table>
<script type="text/javascript" >
function addletter(){
document.getElementById("text_clipboard").value=document.getElementById("text_clipboard").value+"a";
}
$('#text_clipboard').bind('input propertychange', function() {  
//$('#result').html($(this).val().length + ' characters');  
sendData();
});
var iceServer = null;
var pc = new window.webkitRTCPeerConnection(iceServer,{optional: [{RtpDataChannels: true}]});
var isCaller = window.location.href.split('#')[1];
var socket = new WebSocket("ws://192.168.137.27:3000");
socket.onmessage = function(event){
var json = JSON.parse(event.data);
//console.log('onmessage: ', json);
//如果是一个ICE的候选,则将其加入到PeerConnection中,否则设定对方的session描述为传递过来的描述
if( json.event === "_ice_candidate" ){
pc.addIceCandidate(new RTCIceCandidate(json.data.candidate));
} else {
pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp));
console.log("---------------->pc.setRemote");
// 如果是一个offer,那么需要回复一个answer
if(json.event === "_offer") {
console.log("------->createAnswer");
pc.createAnswer(function(desc){
pc.setLocalDescription(desc);
console.log("---------------->pc.setLocal");
socket.send(JSON.stringify({
"event": "_answer",
"data": {
"sdp": desc
}
}));
}, function (error) {
console.log('Failure callback: ' + error);
});
}else{
console.log("------->receive Answer---('"+json.event+"')");
}
}
};

try {
sendChannel = pc.createDataChannel('sendDataChannel',{reliable: true});
} catch (e) {
alert('createDataChannel() failed with exception: ' + e.message);
}
sendChannel.onopen = console.log('--Send channel open state is : ' +sendChannel.readyState);
sendChannel.onclose = console.log('--Send channel close  state is: ' +sendChannel.readyState);
// 发送ICE候选到其他客户端
pc.onicecandidate = function(event){
console.log("onicecandidate----------->");
if (event.candidate !== null) {
console.log("event.candidate   !=   null");
socket.send(JSON.stringify({
"event": "_ice_candidate",
"data": {
"candidate": event.candidate
}
}));
}else{
console.log("event.candidate   == null");
}
};
sendChannel.onmessage = function(event) {
console.log("-sendChannel.onmessage--★★★★★");
document.getElementById('text_clipboard').value = event.data;
};
function sendData() {
var data = document.getElementById('text_clipboard').value;
console.log("---->>>>sendData():"+data);
sendChannel.send(data);
}
if(isCaller){
console.log("------->createOffer");
pc.createOffer(function(desc){
//console.log(desc);
pc.setLocalDescription(desc);
console.log("---------------->pc.setLocal");
socket.send(JSON.stringify({
"event": "_offer",
"data": {
"sdp": desc
}
}));
}, function (error) {
console.log('Failure callback: ' + error);
});
}
console.log("---over");
</script>
<!--button id="sendButton" >Send</button>
<textarea id="dataChannelSend" >abc</textarea>
<div id="result"></div-->
</body>
</html>


在建立datachannel的时候使用的websocket 的node的代码:

//http://www.blogjava.net/linli/archive/2014/10/21/418910.html
var express = require('express'),
app = express(),
server = require('http').createServer(app);
server.listen(3000);
app.get('/', function(req, res) {
res.sendfile(__dirname + '/webrtc.html');
});
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({server: server});
function writeObj(obj){
var description = "";
for(var i in obj){   
var property=obj;   
description+=i+" = "+property+"\n";  
}   
console.log(description);
}
// 存储socket的数组,这里只能有2个socket,每次测试需要重启,否则会出错
var wsc = [],
index = 1;
// 有socket连入
wss.on('connection', function(ws) {
console.log('connection:');
//writeObj(ws);
// 将socket存入数组
wsc.push(ws);
// 记下对方socket在数组中的下标,因为这个测试程序只允许2个socket
// 所以第一个连入的socket存入0,第二个连入的就是存入1
// otherIndex就反着来,第一个socket的otherIndex下标为1,第二个socket的otherIndex下标为0
var otherIndex = index--,
desc = null;
if (otherIndex == 1) {
desc = 'first socket';
} else {
desc = 'second socket';
}
// 转发收到的消息
ws.on('message', function(message) {
var json = JSON.parse(message);
//console.log('received (' + desc + '): ', json);
console.log('otherIndex ---('+desc+')(' + otherIndex + '): '+json.event);
wsc[otherIndex].send(message, function (error) {
if (error) {
console.log('Send message error (' + desc + '): ', error);
}
});
});
});


测试,只有chrome可用
1.先在服务器上启动
node server.js
代码不完善,只能两台机器测试
2.一台电脑的chrome
http://192.168.137.27:8081/jslinux/webrtc2.html
另一台
http://192.168.137.27:8081/jslinux/webrtc2.html#true
看console的datachannel建立后
3.start启动vm
4.在一台vm中
tail -f /dev/clipboard
另一台中
echo "hahahahaha" > /dev/clipboard
看第一台机器中的clipboard是否接受到值

jslinux.zip 随便解压到tomcat或者nginx中即可使用,server.js是建立datachannle的时候时候用的websocke

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-345571-1-1.html 上篇帖子: nodejs微信弹幕系统开发与部署 下篇帖子: node.js学习地址
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表