有沒有做任務(wù)能兌換現(xiàn)金的網(wǎng)站百度提交網(wǎng)址入口
概要
高拍儀硬件通信原理,WebSocket源碼解析(JavaScript)
WebSocket 是 HTML5 開始提供的一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議。
WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)。在 WebSocket API 中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。
在 WebSocket API 中,瀏覽器和服務(wù)器只需要做一個(gè)握手的動(dòng)作,然后,瀏覽器和服務(wù)器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。
現(xiàn)在,很多網(wǎng)站為了實(shí)現(xiàn)推送技術(shù),所用的技術(shù)都是 Ajax 輪詢。輪詢是在特定的的時(shí)間間隔(如每1秒),由瀏覽器對(duì)服務(wù)器發(fā)出HTTP請(qǐng)求,然后由服務(wù)器返回最新的數(shù)據(jù)給客戶端的瀏覽器。這種傳統(tǒng)的模式帶來很明顯的缺點(diǎn),即瀏覽器需要不斷的向服務(wù)器發(fā)出請(qǐng)求,然而HTTP請(qǐng)求可能包含較長的頭部,其中真正有效的數(shù)據(jù)可能只是很小的一部分,顯然這樣會(huì)浪費(fèi)很多的帶寬等資源。
HTML5 定義的 WebSocket 協(xié)議,能更好的節(jié)省服務(wù)器資源和帶寬,并且能夠更實(shí)時(shí)地進(jìn)行通訊。
ps:本來想寫sm4加密和解密算法的,但是sm3一個(gè)加密都看的我頭昏昏的,就先不為難自己了,說說WebSocket的源碼解析吧
源自:?HTML5 WebSocket | 菜鳥教程 (runoob.com)
整體架構(gòu)流程
擬人化展示從HTTP協(xié)議升級(jí)到WebSocket協(xié)議的過程:
1、發(fā)送一個(gè)GET請(qǐng)求
關(guān)鍵: Upgrade: websocket; Connection: Upgrade;
這兩個(gè)就告訴服務(wù)器,我要發(fā)起websocket協(xié)議,我不是HTTP。
2、服務(wù)器收到了協(xié)議,返回一個(gè) Switching Protocol, 這樣就連接成功了。
3、接下來的通信都是websocket, 這樣就很好的連接了。
源自:WebSocket建立連接的過程_websocket如何建立連接-CSDN博客
?
技術(shù)名詞解釋
連接請(qǐng)求:Connection: Upgrade;
通信消息數(shù)據(jù):(二進(jìn)制消息)
技術(shù)細(xì)節(jié)
一、建立連接:
在高拍儀初始化時(shí)建立連接
初始化,設(shè)置顯示相機(jī)屏幕大小,設(shè)置自動(dòng)裁剪(初始化后才能設(shè)置)
function LoadCameraDocument() {if (!window.WebSocket) {alert("瀏覽器不支持HTML5,請(qǐng)更新瀏覽器或者使用其它瀏覽器");}//console.log("LoadCameraDocument");var obj = document.getElementById("CameraCtl");Cam_ControlInit(obj, 0, 0, 600, 400);// 模擬異步硬件初始化setTimeout(function () {// 設(shè)置自動(dòng)裁剪SetCameraCutMode();}, 2500); // 假設(shè)2.5秒后硬件初始化完成// 模擬異步硬件初始化setTimeout(function () {// 設(shè)置自動(dòng)裁剪SetCameraCutMode();}, 5000); // 完不成再來一下
}
?連接WebSocket,初始化相機(jī)
//*************攝像頭操作初始化***************
function Cam_ControlInit(documentObj, mX, mY, mwidth, mheight) {WebSocketConnect();InitCanvas(documentObj, mX, mY, mwidth, mheight);//console.log("Cam_ControlInit");
}
?設(shè)置連接地址和開啟時(shí)函數(shù),
????????設(shè)置心跳檢測、斷線重連、獲取設(shè)備數(shù)目
? ? ? ? 完成后輸出連接成功 "socket.onopen"
socket = new WebSocket("ws://127.0.0.1:22225");
socket.binaryType = "arraybuffer";socket.onopen = function (event) {//heartCheck.reset().start(); heartCheck();isSocketConnect = true;clearInterval(intervalId);//if (isOpenMainCamera == false) Cam_GetDevCount();console.log("socket.onopen");};
二、發(fā)送數(shù)據(jù):
首先要有心跳,if (isSocketConnect)
其次,創(chuàng)建二進(jìn)制數(shù)組 var aDataArray = new Uint8Array(totalLen)
然后,消息分裝
最后,發(fā)送二進(jìn)制消息 socket.send(aDataArray.buffer);
示例“處理拍照邏輯發(fā)送消息邏輯”代碼:
function CaptureImage(fileAddr) {if (isSocketConnect) {// var pathArray = stringToUint8Array(fileAddr);if (fileAddr == "") {var packageCount = 1;var len = 0;var pindex = 0;var totalLen = 12;var aDataArray = new Uint8Array(totalLen);aDataArray[0] = 0x77;aDataArray[1] = 0x88;aDataArray[2] = 0x10;aDataArray[3] = 0x00;aDataArray[4] = len >> 16 & 0xff;aDataArray[5] = len >> 8 & 0xff;aDataArray[6] = len & 0xff;aDataArray[7] = packageCount >> 8 & 0xff; //包總數(shù)aDataArray[8] = packageCount & 0xff; //包總數(shù)aDataArray[9] = 0; //分包長度aDataArray[10] = pindex >> 8 & 0xff; //包序號(hào)aDataArray[11] = pindex & 0xff; //包序號(hào)console.log("pindex:" + pindex);socket.send(aDataArray.buffer);} else {var path = encodeURI(fileAddr);//console.log(path);var pathArray = stringToByte(path);var len = pathArray.length;var packageCount = 0;var tmpLen = len;while (tmpLen > 0) {tmpLen = tmpLen - 90;packageCount++;}console.log("packageCount:" + packageCount);var pindex = 0;tmpLen = len;while (tmpLen > 0) {tmpLen = tmpLen - 90;if (tmpLen > 0) {var totalLen = 90 + 12;var aDataArray = new Uint8Array(totalLen);aDataArray[0] = 0x77;aDataArray[1] = 0x88;aDataArray[2] = 0x10;aDataArray[3] = 0x00;aDataArray[4] = len >> 16 & 0xff;aDataArray[5] = len >> 8 & 0xff;aDataArray[6] = len & 0xff;aDataArray[7] = packageCount >> 8 & 0xff; //包總數(shù)aDataArray[8] = packageCount & 0xff; //包總數(shù)aDataArray[9] = 90; //分包長度aDataArray[10] = pindex >> 8 & 0xff; //包序號(hào)aDataArray[11] = pindex & 0xff; //包序號(hào)console.log("pindex:" + pindex);for (var i = 0; i < 90; i++) {aDataArray[12 + i] = pathArray[i + pindex * 90];}socket.send(aDataArray.buffer);} else {var totalLen = 90 + tmpLen + 12; // 此時(shí)tmpLen為負(fù)數(shù),做加法運(yùn)算var aDataArray = new Uint8Array(totalLen);aDataArray[0] = 0x77;aDataArray[1] = 0x88;aDataArray[2] = 0x10;aDataArray[3] = 0x00;aDataArray[4] = len >> 16 & 0xff;aDataArray[5] = len >> 8 & 0xff;aDataArray[6] = len & 0xff;aDataArray[7] = packageCount >> 8 & 0xff; //包總數(shù)aDataArray[8] = packageCount & 0xff; //包總數(shù)aDataArray[9] = 90 + tmpLen; //分包長度aDataArray[10] = pindex >> 8 & 0xff; //包序號(hào)aDataArray[11] = pindex & 0xff; //包序號(hào)console.log("pindex:" + pindex);for (var i = 0; i < (90 + tmpLen); i++) {aDataArray[12 + i] = pathArray[i + pindex * 90];}socket.send(aDataArray.buffer);}pindex++;toSleep(80);}}}
}
三、響應(yīng)數(shù)據(jù):
例如:拍照時(shí)數(shù)據(jù)處理
創(chuàng)建onmessage方法,心跳檢測必寫
socket.onmessage = function (event) {// heartCheck.reset().start(); var rDataArr = new Uint8Array(event.data);if (rDataArr.length > 0) {// WebSocket心跳檢測if (rDataArr[0] == 0x11 && rDataArr[1] == 0x11 && rDataArr[2] == 0x11) {console.log("socket心跳 ?");}// 處理rDataArr數(shù)據(jù)// 省略...示例代碼}}
響應(yīng)數(shù)據(jù)方法:socket.onmessage = function (event) {}
示例"處理拍照結(jié)果返回響應(yīng)邏輯"代碼:
//拍照結(jié)果返回
if (rDataArr[2] == 0x10) {var flag;if (rDataArr[3] == 0x01) {flag = 0;var imgpathLen = rDataArr[4] * 256 + rDataArr[5];if (imgpathLen == 0) {var base64Len = rDataArr[6] * 65536 + rDataArr[7] * 256 + rDataArr[8];var imgPathStr = "";var base64Data = new Uint8Array(base64Len);for (var i = 0; i < base64Len; i++) {base64Data[i] = rDataArr[9 + imgpathLen + i];}var base64Str = Uint8ArrayToString(base64Data);GetCaptrueImgResultCB(flag, imgPathStr, base64Str);} else {var base64Len = rDataArr[6] * 65536 + rDataArr[7] * 256 + rDataArr[8];var pData = new Uint8Array(imgpathLen);for (var i = 0; i < imgpathLen; i++) {pData[i] = rDataArr[9 + i];}var str = byteToString(pData);var imgPathStr = decodeURIComponent(str);var base64Data = new Uint8Array(base64Len);for (var i = 0; i < base64Len; i++) {base64Data[i] = rDataArr[9 + imgpathLen + i];}var base64Str = Uint8ArrayToString(base64Data);GetCaptrueImgResultCB(flag, imgPathStr, base64Str);}}if (rDataArr[3] == 0x02) {flag = 2;GetCaptrueImgResultCB(flag, "", "");}}
小結(jié)
WebSocket是一種在Web瀏覽器和服務(wù)器之間進(jìn)行全雙工通信的協(xié)議,通過它可以實(shí)現(xiàn)實(shí)時(shí)的數(shù)據(jù)傳輸。建立WebSocket連接的過程包括發(fā)送一個(gè)GET請(qǐng)求并指定協(xié)議升級(jí),服務(wù)器返回一個(gè)Switching Protocol響應(yīng),連接成功后即可進(jìn)行WebSocket通信。在實(shí)際應(yīng)用中,可以通過WebSocket發(fā)送和接收二進(jìn)制消息來實(shí)現(xiàn)各種功能,例如拍照、傳輸文件等。需要注意的是,為了保持連接的穩(wěn)定性,通常會(huì)實(shí)現(xiàn)心跳檢測和斷線重連功能。
-
深入理解WebSocket協(xié)議:通過實(shí)際編碼,我更深入地理解了WebSocket協(xié)議的工作原理和建立連接的過程。
-
網(wǎng)絡(luò)通信能力提升:通過處理WebSocket通信的邏輯,我提升了自己的網(wǎng)絡(luò)通信能力,包括發(fā)送和接收數(shù)據(jù)的處理能力。
-
異步編程理解:WebSocket通信通常是異步的,我鞏固了如何處理異步通信,例如通過回調(diào)函數(shù)處理接收到的消息。
-
實(shí)踐經(jīng)驗(yàn):通過實(shí)際編寫WebSocket通信相關(guān)的代碼,我積累了寶貴的實(shí)踐經(jīng)驗(yàn),可以幫助我更好地理解和應(yīng)用相關(guān)知識(shí)。
-
問題解決能力:在編寫過程中可能遇到了各種問題,通過解決這些問題,我提升了自己的問題解決能力和調(diào)試技巧。