webrtc学习笔记七(datachannel在jslinux的应用,nodejs版本)
程序员文章站
2022-07-08 16:42:22
...
目标:
两个浏览器的jslinux可以进行数据交互
fabrice的jslinux是跑在浏览器中的linux,
提供了通过
/dev/clipboard 与<textare>交互的功能,交互的方法是clipboard_set
可以在jslinux.js中的clipboard_set方法中加入
datachannel的send方法,使两个浏览器中的textare有数据同步
从而是jslinux中通过一个linux的clipboard与另一个jslinux的clipboard交互
jslinux.js中修改的代码:
jslinux的html修改的代码:
在建立datachannel的时候使用的websocket 的node的代码:
测试,只有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
两个浏览器的jslinux可以进行数据交互
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">© 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" onclick="clear_clipboard();"><br><textarea row="4" cols="16" id="text_clipboard" ></textarea></br> <input type="button" value="addletter" onclick="addletter();"> <input type="button" value="start" onclick="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" onclick="sendData()">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[i]; 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