W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
ModPHP 提供了一個(gè)默認(rèn)的 Socket 服務(wù)器程序邏輯,用以配合模塊數(shù)據(jù)操作。
要啟動(dòng)默認(rèn)的 Socket 服務(wù)器,你只需要在服務(wù)器的控制臺(tái)中運(yùn)行站點(diǎn)根目錄的 socket-server.php 文件即可。如果你使用 Apache 服務(wù)器,你也可以在瀏覽器中開啟,但需要驗(yàn)證管理員權(quán)限。注意:瀏覽器可能無法加載 socket-server.php 頁(yè)面輸出的內(nèi)容,訪問后直接關(guān)閉窗口即可。
監(jiān)聽端口由 config('mod.SocketServer.port') 設(shè)置,默認(rèn)為 8080。
開啟 Socket 服務(wù)器不會(huì)影響正常的 Apache 網(wǎng)站,但是如果你的程序代碼經(jīng)過改動(dòng)(例如更新系統(tǒng)),則需要重新啟動(dòng) Socket 服務(wù)。如果你是在瀏覽器中啟用 Socket 服務(wù)器的,那么你需要通過關(guān)閉 Apache 來關(guān)閉 Socket 服務(wù)器,然后才能再次重啟它。
當(dāng) Socket 服務(wù)器啟動(dòng)之后,你就可以通過 JSON 進(jìn)行數(shù)據(jù)交換了,所有能夠通過 URL 訪問 mod.php 進(jìn)行請(qǐng)求的操作,也能通過 Socket 服務(wù)器進(jìn)行。
該 Socket 服務(wù)器僅用于傳輸文本數(shù)據(jù)(JSON),不支持傳輸二進(jìn)制數(shù)據(jù),但是,你可以將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為文本(例如圖像轉(zhuǎn) base64)進(jìn)行傳輸,或者自己編寫另外的 Socket 程序邏輯。
客戶端通過發(fā)送 JSON 數(shù)據(jù)向服務(wù)器提交請(qǐng)求,服務(wù)器將操作結(jié)果回應(yīng)以 JSON 數(shù)據(jù),實(shí)現(xiàn)前后端一致。需要注意的是,除非是重現(xiàn)會(huì)話,否則 JSON 中必須包含 {obj} 和 {act} 屬性,其他屬性將作為請(qǐng)求參數(shù)。
如果客戶端已經(jīng)通過其他方式進(jìn)行了用戶登錄,如 AJAX,那么可以將 cookie 中的 Session ID 傳給 Socket 服務(wù)器,從而在 WebSocket 中恢復(fù)登錄狀態(tài)。當(dāng)然,如果你沒有通過其他方式進(jìn)行登錄,也可以使用 WebSocket 進(jìn)行登錄,登錄后會(huì)將用戶信息和 Session ID 通過 JSON 同時(shí)返回給客戶端,客戶端將 Session ID 寫入 Cookie 中,從而在瀏覽其他頁(yè)面時(shí)也保持會(huì)話。
重現(xiàn)會(huì)話示例:
var ws = new WebSocket('ws://localhost:8080');
ws.open = function(){
var sid = document.cookie.match(/PHPSESSID=(.*)\b/)[1];
ws.send(JSON.stringify({PHPSESSID: sid}));
}
登錄示例:
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function(){
var data = {
obj: 'user',
act: 'login',
user: 'someone',
user_password: 'not_show_here'
};
ws.send(JSON.stringify(data));
}
ws.onmessage = function(e){
var result = JSON.parse(e.data);
if(result.success && result.PHPSESSID){
document.cookie += 'PHPSESSID='+result.PHPSESSID; //將 Session ID 寫到 cookie 中
}
}
需要注意的是,在重現(xiàn)會(huì)話或者使用 WebSocket 進(jìn)行登錄之后,之后的其他操作就已經(jīng)運(yùn)行在已登錄狀態(tài)了,服務(wù)器會(huì)保存登錄信息,不需要客戶端再提交 Session ID。例如,要獲取當(dāng)前登錄用戶的信息,只需要這樣做:
ws.send(JSON.stringify({obj: 'user', act: 'getMe'}));
Socket 服務(wù)器也支持頁(yè)面判斷功能,需要客戶端發(fā)送數(shù)據(jù)時(shí)同時(shí)發(fā)送 HTTP_REFERER 為當(dāng)前 URL 地址給服務(wù)器(自定義來路頁(yè)面)。例如上面獲取當(dāng)前用戶信息的例子,可以這樣:
ws.send(JSON.stringify({obj: 'user', act: 'getMe', HTTP_REFERER: location.href}));
雖然,ModPHP 提供了非常便捷的搭建 Socket 服務(wù)器的方法,但是你必不可濫用它。例如,在一個(gè) HTML 頁(yè)面,你應(yīng)該只設(shè)置一個(gè)指向同一服務(wù)器的 WebSocket 的實(shí)例。更好的就是,使用 iframe 等方式,實(shí)現(xiàn)多個(gè)頁(yè)面使用同一個(gè) WebSocket 實(shí)例。這樣可以有效地節(jié)約服務(wù)器資源,從而加快網(wǎng)站運(yùn)行速度。
其他客戶端類型連接服務(wù)器:
其他客戶端類型或者其他編程語言編寫得 Socket 客戶端的連接和通訊與 WebSocket 大同小異,但和 WebSocket 協(xié)議相比,這些客戶端不需要使用復(fù)雜的編碼和解碼過程,直接發(fā)送原始報(bào)文即可。
ModPHP 提供了在 Socket 服務(wù)器下進(jìn)行網(wǎng)站地址判斷的功能(如果網(wǎng)站地址未固定),這個(gè)特性,是依賴客戶端發(fā)送的握手包來實(shí)現(xiàn)的。在 WebSocket 協(xié)議中,客戶端會(huì)將一個(gè) HTTP 請(qǐng)求頭作為握手包發(fā)送給服務(wù)器。ModPHP 利用這個(gè)請(qǐng)求頭,來計(jì)算出網(wǎng)站的 URL 地址。
因此,你也可以在普通的 Socket 連接中,發(fā)送一個(gè) HTTP 請(qǐng)求頭格式的數(shù)據(jù),作為握手包,來讓服務(wù)器自動(dòng)“計(jì)算”網(wǎng)站的 URL 地址。
將 WebSocket 運(yùn)行于多線程中:
請(qǐng)查看《將 Socket 服務(wù)器運(yùn)行于多線程環(huán)境中》。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: