欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

扣丁學(xué)堂PHP培訓(xùn)之五分鐘教你編寫一個(gè)實(shí)時(shí)彈幕網(wǎng)站

2018-01-16 10:59:55 1704瀏覽

在現(xiàn)如今,隨著互聯(lián)網(wǎng)時(shí)代飛速的發(fā)展,比如目前較火的直播平臺(tái)都有實(shí)時(shí)彈幕滾動(dòng),而小編首先要搞定的是前端頁(yè)面,最起碼得有個(gè)框,那么問(wèn)題來(lái)了,這些視頻彈幕網(wǎng)站如何做到實(shí)時(shí)同步的?PHP如何開(kāi)發(fā)一個(gè)類似的網(wǎng)站?


經(jīng)過(guò)搜索,找到了一個(gè)jQuery.danmu.js的開(kāi)源項(xiàng)目??戳艘幌聅tar的人還挺多github.com/chiruom/jquery.danmu.js


原來(lái)是源文件中的jQuery插件的問(wèn)題。在src目錄下,并沒(méi)有該文件

<scriptsrc="../src/jquery-2.1.4.min.js"></script>

算了還是調(diào)用百度的在線jQuery插件吧

<scriptsrc="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>

再一刷新,不出預(yù)料,成功運(yùn)行。



后端,那就先來(lái)說(shuō)說(shuō)彈幕的原理吧。彈幕,就相當(dāng)于一個(gè)公共聊天室,都是一個(gè)客戶端發(fā)送消息給服務(wù)端,服務(wù)端再將收到的消息廣播給其他的客戶端。

用傳統(tǒng)的ajax輪詢嗎?不行,這樣效率太低,想想各大火爆的直播平臺(tái)都是同一時(shí)間幾萬(wàn)人在線,幾千人同時(shí)發(fā)彈幕,如果靠ajax輪詢一個(gè)PHP接口的話服務(wù)器會(huì)吃不消的。且彈幕消息存儲(chǔ)方案略顯復(fù)雜,有人問(wèn)為什么要存儲(chǔ)呢?因?yàn)閍jax使用的HTTP協(xié)議是無(wú)狀態(tài)協(xié)議,A客戶端和B客戶端之間對(duì)于服務(wù)器來(lái)說(shuō)沒(méi)有任何標(biāo)志,如果服務(wù)器要確保A客戶端和B客戶端分別在兩次請(qǐng)求的時(shí)候服務(wù)器只返回這兩個(gè)客戶端沒(méi)有獲取過(guò)的彈幕消息,那么服務(wù)器端就必須使用一個(gè)緩存來(lái)標(biāo)識(shí)某某客戶端看過(guò)哪條彈幕消息。綜上所述ajax可以實(shí)現(xiàn)小規(guī)模的彈幕通信方案,但是很麻煩。

好在最新的HTML5中加入了WebSocket協(xié)議,我們可以通WebSocket這種基于HTTP協(xié)議之上的即時(shí)通信協(xié)議來(lái)替代ajax這種傳統(tǒng)的我問(wèn)你答的老舊通信模式。而我們是PHPer,對(duì)于我們這種只懂PHP的人該如何編寫WebSocket服務(wù)端呢?好在我們又得知PHP有一個(gè)Swoole擴(kuò)展,我們?cè)赑HP語(yǔ)言中使用它可以很方便的構(gòu)建一個(gè)WebSocket服務(wù)端。

關(guān)于Swoole,下面這段是其官網(wǎng)上的話:

PHP的異步、并行、高性能網(wǎng)絡(luò)通信引擎,使用純C語(yǔ)言編寫,提供了PHP語(yǔ)言的異步多線程服務(wù)器,異步TCP/UDP網(wǎng)絡(luò)客戶端,異步MySQL,異步Redis,數(shù)據(jù)庫(kù)連接池,AsyncTask,消息隊(duì)列,毫秒定時(shí)器,異步文件讀寫,異步DNS查詢。Swoole內(nèi)置了Http/WebSocket服務(wù)器端/客戶端、Http2.0服務(wù)器端。

Swoole可以廣泛應(yīng)用于互聯(lián)網(wǎng)、移動(dòng)通信、企業(yè)軟件、云計(jì)算、網(wǎng)絡(luò)游戲、物聯(lián)網(wǎng)(IOT)、車聯(lián)網(wǎng)、智能家居等領(lǐng)域。使用PHP+Swoole作為網(wǎng)絡(luò)通信框架,可以使企業(yè)IT研發(fā)團(tuán)隊(duì)的效率大大提升,更加專注于開(kāi)發(fā)創(chuàng)新產(chǎn)品。

還有一個(gè)問(wèn)題需要解決,那就是,這個(gè)jquery.danmu.js是基于彈幕運(yùn)行時(shí)間的一個(gè)插件。那又要如何做到實(shí)時(shí)呢。開(kāi)始博主想的是在服務(wù)器端規(guī)定一個(gè)時(shí)間(即其連接時(shí)間),當(dāng)有客戶端連接時(shí),返回服務(wù)器的當(dāng)前時(shí)間戳,然后以此為依據(jù)開(kāi)始計(jì)時(shí)。但是遇到的問(wèn)題如下:

該彈幕插件是按十分之秒計(jì)時(shí)制度。

各瀏覽器上js的定時(shí)器的運(yùn)行時(shí)間略有差異。

時(shí)間不能完全同步。

websocket是實(shí)時(shí)通信的,哎,那所有客戶端的時(shí)間,不一致就不一致吧,彈幕發(fā)的時(shí)間根據(jù)各個(gè)客戶端的為準(zhǔn)唄,都以當(dāng)前各個(gè)客戶端的時(shí)間來(lái)發(fā),websocket只傳遞不包含時(shí)間的數(shù)據(jù)(好吧有點(diǎn)繞,我自己都感覺(jué)說(shuō)饒了),咱們直接來(lái)上代碼吧。

index.html

<!DOCTYPEhtml>

<htmllang="en">

<head>

<metacharset="utf-8">

<metaname="viewport"content="width=device-width,initial-scale=1.0">

<title>彈幕madebydiligentyang</title>

<style>

body{

font-family:"MicrosoftYaHei"!important;

font-color:#222;

}

pre{

line-height:2em;

font-family:"MicrosoftYaHei"!important;

}

h4{

line-height:2em;

}

#danmuarea{

position:relative;

background:#222;

width:800px;

height:445px;

margin-left:auto;

margin-right:auto;

}

.center{

text-align:center;

}

.ctr{

font-size:1em;

line-height:2em;

}

</style>

<scriptsrc="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>

<scriptsrc="../dist/jquery.danmu.min.js"></script>

</head>

<bodyclass="center">

Demo<br><br>

<!--黑背景和彈幕區(qū)-->

<divid="danmuarea">

<divid="danmu">

</div>

</div>

<!--控制區(qū)-->

<divclass="ctr">

<buttontype="button"onclick="pauser()">彈幕暫停</button>&nbsp;&nbsp;&nbsp;&nbsp;

<buttontype="button"onclick="resumer()">彈幕繼續(xù)</button>&nbsp;&nbsp;&nbsp;&nbsp;

顯示彈幕:<inputtype='checkbox'checked='checked'id='ishide'value='is'onchange='changehide()'>&nbsp;&nbsp;&nbsp;&nbsp;

彈幕透明度:

<inputtype="range"name="op"id="op"onchange="op()"value="100"><br>

當(dāng)前彈幕運(yùn)行時(shí)間(秒):<spanid="time"></span>&nbsp;&nbsp;

<!--設(shè)置當(dāng)前彈幕時(shí)間(秒):<inputtype="text"id="set_time"max=20/>

<buttontype="button"onclick="settime()">設(shè)置</button>-->

<br>

發(fā)彈幕:

<selectname="color"id="color">

<optionvalue="white">白色</option>

<optionvalue="red">紅色</option>

<optionvalue="green">綠色</option>

<optionvalue="blue">藍(lán)色</option>

<optionvalue="yellow">黃色</option>

</select>

<selectname="size"id="text_size">

<optionvalue="1">大文字</option>

<optionvalue="0">小文字</option>

</select>

<selectname="position"id="position">

<optionvalue="0">滾動(dòng)</option>

<optionvalue="1">頂端</option>

<optionvalue="2">底端</option>

</select>

<inputtype="textarea"id="text"max=300/>

<buttontype="button"onclick="send()">發(fā)送</button>

</div>

<script>

//WebSocket

varwsServer='ws://123.206.61.229:9505';

varwebsocket=newWebSocket(wsServer);

websocket.onopen=function(evt){

console.log("ConnectedtoWebSocketserver.");

/*websocket.send("gaga");*/

//連上之后就打開(kāi)彈幕

$('#danmu').danmu('danmuResume');

};

websocket.onclose=function(evt){

console.log("Disconnected");

};

websocket.onmessage=function(evt){

console.log('Retrieveddatafromserver:'+evt.data);

vartime=$('#danmu').data("nowTime")+1;

vartext_obj=evt.data+',"time":'+time+'}';//獲取加上當(dāng)前時(shí)間

console.log(text_obj);

varnew_obj=eval('('+text_obj+')');

$('#danmu').danmu("addDanmu",new_obj);//添加彈幕

};

websocket.onerror=function(evt,e){

console.log('Erroroccured:'+evt.data);

};

//初始化

$("#danmu").danmu({

left:0,

top:0,

height:"100%",

width:"100%",

speed:20000,

opacity:1,

font_size_small:16,

font_size_big:24,

top_botton_danmu_time:6000

});

//一個(gè)定時(shí)器,監(jiān)視彈幕時(shí)間并更新到頁(yè)面上

functiontimedCount(){

$("#time").text($('#danmu').data("nowTime"));

t=setTimeout("timedCount()",50)

}

timedCount();

functionstarter(){

$('#danmu').danmu('danmuStart');

}

functionpauser(){

$('#danmu').danmu('danmuPause');

}

functionresumer(){

$('#danmu').danmu('danmuResume');

}

functionstoper(){

$('#danmu').danmu('danmuStop');

}

functiongetime(){

alert($('#danmu').data("nowTime"));

}

functiongetpaused(){

alert($('#danmu').data("paused"));

}

//發(fā)送彈幕,使用了文檔README.md第7節(jié)中推薦的方法

functionsend(){

vartext=document.getElementById('text').value;

varcolor=document.getElementById('color').value;

varposition=document.getElementById('position').value;

//vartime=$('#danmu').data("nowTime")+1;

varsize=document.getElementById('text_size').value;

//vartext_obj='{"text":"'+text+'","color":"'+color+'","size":"'+size+'","position":"'+position+'","time":'+time+'}';

//為了處理簡(jiǎn)單,方便后續(xù)加time,和isnew,就先醬紫發(fā)一半吧。

//注:time為彈幕出來(lái)的時(shí)間,isnew為是否加邊框,自己發(fā)的彈幕,常理上來(lái)說(shuō)是有邊框的。

vartext_obj='{"text":"'+text+'","color":"'+color+'","size":"'+size+'","position":"'+position+'"';

//利用websocket發(fā)送

websocket.send(text_obj);

//清空相應(yīng)的內(nèi)容

document.getElementById('text').value='';

}

//調(diào)整透明度函數(shù)

functionop(){

varop=document.getElementById('op').value;

$('#danmu').danmu("setOpacity",op/100);

}

//調(diào)隱藏顯示

functionchangehide(){

varop=document.getElementById('op').value;

op=op/100;

if(document.getElementById("ishide").checked){

$("#danmu").danmu("setOpacity",1)

}else{

$("#danmu").danmu("setOpacity",0)

}

}

//設(shè)置彈幕時(shí)間

functionsettime(){

vart=document.getElementById("set_time").value;

t=parseInt(t)

$('#danmu').danmu("setTime",t);

}

</script>

</body>

</html>

上述代碼需要注意的是websocket的建立和接收,以及send方法中對(duì)彈幕的處理。

ws_server.php

<?php

//創(chuàng)建websocket服務(wù)器對(duì)象,監(jiān)聽(tīng)0.0.0.0:9505端口

$ws=newswoole_websocket_server("0.0.0.0",9505);

//監(jiān)聽(tīng)WebSocket連接打開(kāi)事件

$ws->on('open',function($ws,$request){

//var_dump($request->fd,$request->get,$request->server);

//相當(dāng)于記錄一個(gè)日志吧,有連接時(shí)間和連接ip

echo$request->fd.'-----time:'.date("Y-m-dH:i:s",$request->server['request_time']).'--IP--'.$request->server['remote_addr'].'-----';

});

//監(jiān)聽(tīng)WebSocket消息事件

$ws->on('message',function($ws,$frame){

//記錄收到的消息,可以寫到日志文件中

echo"Message:{$frame->data}\n";

//遍歷所有連接,循環(huán)廣播

foreach($ws->connectionsas$fd){

//如果是某個(gè)客戶端,自己發(fā)的則加上isnew屬性,否則不加

if($frame->fd==$fd){

$ws->push($frame->fd,$frame->data.',"isnew":""');

}else{

$ws->push($fd,"{$frame->data}");

}

}

});

//監(jiān)聽(tīng)WebSocket連接關(guān)閉事件

$ws->on('close',function($ws,$fd){

echo"client-{$fd}isclosed\n";

});

$ws->start();

運(yùn)行方法:

輸入phpws_server.php先啟動(dòng)服務(wù)器端的websocket。如果要后臺(tái)運(yùn)行,且不隨用戶終端關(guān)閉而斷開(kāi),需要?jiǎng)?chuàng)建一個(gè)log.txt用于存取上述輸出的東西,然后輸入nohupphpws_server.php>log.txt&即可。



注,如果要用此項(xiàng)目,需要自行修改自己的服務(wù)器ip地址。只需要修改varwsServer='ws://123.206.61.229:9505';處即可,后臺(tái)代碼不需要做任何處理。

最后希望對(duì)同學(xué)們有所幫助。想要學(xué)習(xí)PHP培訓(xùn)技術(shù)的小伙伴歡迎選擇扣丁學(xué)堂進(jìn)行學(xué)習(xí)。扣丁學(xué)堂不僅有專業(yè)的老師和與時(shí)俱進(jìn)的課程體系,還有大量的PHP視頻教程供學(xué)員觀看學(xué)習(xí),想要學(xué)到實(shí)用技術(shù)高薪就業(yè)的小伙伴抓緊時(shí)間行動(dòng)吧??鄱W(xué)堂PHP技術(shù)交流群:374332265。





【關(guān)注微信公眾號(hào)獲取更多的學(xué)習(xí)資料】



查看更多關(guān)于“php培訓(xùn)資訊”的相關(guān)文章>>

標(biāo)簽: PHP培訓(xùn) PHP視頻教程 PHP從入門到精通 PHP學(xué)習(xí)路線圖 PHP開(kāi)發(fā)工程師

熱門專區(qū)

暫無(wú)熱門資訊

課程推薦

微信
微博
15311698296

全國(guó)免費(fèi)咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號(hào)中關(guān)村智誠(chéng)科創(chuàng)大廈4層
京ICP備2021002079號(hào)-2   Copyright ? 2017 - 2022
返回頂部 返回頂部