因?yàn)橹挥姓{(diào)用了accept客戶(hù)端才能連上,你如果accept下面接一個(gè)循環(huán),那么第二個(gè)用戶(hù)不是說(shuō)能不能進(jìn)這個(gè)循環(huán),而是連不進(jìn)……此時(shí)只有第一個(gè)用戶(hù)break出了循環(huán),然后程序回頭再調(diào)用accept,第二個(gè)用戶(hù)才能連上。
為蒲城等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及蒲城網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、蒲城網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
用多進(jìn)程來(lái)處理如何?因?yàn)閍ccept一個(gè)客戶(hù)端以后,應(yīng)該是馬上準(zhǔn)備accept下一個(gè)客戶(hù)端才對(duì),而不是處理完現(xiàn)在這個(gè)客戶(hù)端才accept下一個(gè)客戶(hù)端。
socket_accept以后,直接調(diào)用
pcntl_fork(),此時(shí)進(jìn)程會(huì)分裂為兩個(gè),其中一個(gè)的pnctl_fork返回值是0,另一個(gè)不是0。不是0的那個(gè)直接繼續(xù)調(diào)用socket_accept即可,是0的那個(gè)處理客戶(hù)端請(qǐng)求。
pnctl_fork不知道在windows下能不能用。
不過(guò)返回不是0的那個(gè)進(jìn)程并不是這樣就完事了,還要調(diào)用pcntl_wait防止子進(jìn)程卡在那邊沒(méi)有完全結(jié)束。你可以在主進(jìn)程里時(shí)不時(shí)就調(diào)用這個(gè),配上WNOHANG作為option參數(shù)防止沒(méi)有子進(jìn)程需要wait的時(shí)候卡在那邊。
這都是linux下常用的處理手段。說(shuō)實(shí)話(huà)本來(lái)我想讓你用多線(xiàn)程的,不過(guò)看了一圈不知道php里怎么用線(xiàn)程,倒是找到了用進(jìn)程的方式,所以就
php實(shí)現(xiàn)ios推送的方法:首先把要發(fā)送的消息以及iPhone標(biāo)識(shí)打包,并發(fā)送給APNS;然后查找有相應(yīng)標(biāo)識(shí)的iPhone,并把消息發(fā)送到iPhone;最后把發(fā)來(lái)的消息傳遞給相應(yīng)的應(yīng)用程序,并且按照設(shè)定彈出Push通知即可。
可以分為三個(gè)階段:
第一階段:應(yīng)用程序把要發(fā)送的消息、目的iPhone的標(biāo)識(shí)打包,發(fā)給APNS。
第二階段:APNS在自身的已注冊(cè)Push服務(wù)的iPhone列表中,查找有相應(yīng)標(biāo)識(shí)的iPhone,并把消息發(fā)送到iPhone。
第三階段:iPhone把發(fā)來(lái)的消息傳遞給相應(yīng)的應(yīng)用程序,并且按照設(shè)定彈出Push通知。
推送服務(wù)極光還不錯(cuò),極光多種消息類(lèi)型,開(kāi)發(fā)者可以輕松地通過(guò)極光發(fā)送各個(gè)移動(dòng)平臺(tái)的系統(tǒng)通知,還可以在控制臺(tái)編輯多種富文本展示模板; 極光還提供自定義消息的透?jìng)?,客?hù)端接到消息內(nèi)容后根據(jù)自己的邏輯自由處理。
在php中用百度云推送進(jìn)行消息的推送的方法
1.Android端推送
// 創(chuàng)建Android SDK對(duì)象.
$asdk = new \Vendor\pushsdk\PushSDK(); //自己引入百度云推送的SDK,官網(wǎng)上有文檔詳細(xì)介紹
$channelId = $channelrows;
$message = array (
// 消息的標(biāo)題.
'title' = $title,
// 消息內(nèi)容
'description' = $brief,
//傳廣告id,可以通過(guò)鍵值對(duì)的形式傳多個(gè)值
'custom_content'=array('id'=$id),
);
// 設(shè)置消息類(lèi)型為通知類(lèi)型.
$opts = array (
'msg_type' = 1,
);
// 向目標(biāo)設(shè)備發(fā)送一條消息(群發(fā),指的是通過(guò)前面的篩選之后的channelId進(jìn)行的大量的推送)
$rs = $asdk - pushBatchUniMsg($channelId, $message, $opts);
// 判斷返回值,當(dāng)發(fā)送失敗時(shí), $rs的結(jié)果為false, 可以通過(guò)getError來(lái)獲得錯(cuò)誤信息.
if($rs === false)
{
print_r($asdk-getLastErrorCode());
print_r($asdk-getLastErrorMsg());
}
else{echo "success!";}
2.IOS推送
// 創(chuàng)建Ios SDK對(duì)象.
$isdk = new \Vendor\ipushsdk\IPushSDK();
$channelId = $channelrows;
$message = array (
'aps' = array(
'alert' = $brief, // 消息內(nèi)容
),
'id' =$id, //賬號(hào)ID,這邊能夠以鍵值對(duì)的形式可以傳多個(gè)值
);
// 設(shè)置消息類(lèi)型為 通知類(lèi)型.
$opts = array (
msg_type' = 1,
'deploy_status' = 2, //2是生產(chǎn)狀態(tài),剛開(kāi)始開(kāi)發(fā)測(cè)試時(shí)需要設(shè)置成1進(jìn)行測(cè)試
);
$rs = $isdk-createTag('tag_new'); //通過(guò)創(chuàng)建標(biāo)簽的方式來(lái)實(shí)現(xiàn)群發(fā)的功能
if($rs !== false)
{
if($isdk - addDevicesToTag('tag_new',$channelId) !== false)
{
// 發(fā)送
$rs = $isdk - pushMsgToTag('tag_new',$message,$opts);
//刪除標(biāo)簽
$delRs = $isdk-deleteTag('tag_new');
//判斷返回值,當(dāng)發(fā)送失敗時(shí), $rs的結(jié)果為false, 可以通過(guò)getError來(lái)獲得錯(cuò)誤信息.
if($rs === false)
{
print_r($isdk-getLastErrorCode());
print_r($isdk-getLastErrorMsg());
}
else{echo "success!";}
}
}
后端代碼
push.php
?php
use?Workerman\Worker;
require_once?'./Workerman/Autoloader.php';
//?初始化一個(gè)worker容器,監(jiān)聽(tīng)1234端口
$worker?=?new?Worker('websocket://0.0.0.0:1234');
//?這里進(jìn)程數(shù)必須設(shè)置為1
$worker-count?=?1;
//?worker進(jìn)程啟動(dòng)后建立一個(gè)內(nèi)部通訊端口
$worker-onWorkerStart?=?function($worker)
{
//?開(kāi)啟一個(gè)內(nèi)部端口,方便內(nèi)部系統(tǒng)推送數(shù)據(jù),Text協(xié)議格式?文本+換行符
$inner_text_worker?=?new?Worker('Text://0.0.0.0:5678');
$inner_text_worker-onMessage?=?function($connection,?$buffer)
{
global?$worker;
//?$data數(shù)組格式,里面有uid,表示向那個(gè)uid的頁(yè)面推送數(shù)據(jù)
$data?=?json_decode($buffer,?true);
$uid?=?$data['uid'];
//?通過(guò)workerman,向uid的頁(yè)面推送數(shù)據(jù)
$ret?=?sendMessageByUid($uid,?$buffer);
//?返回推送結(jié)果
$connection-send($ret???'ok'?:?'fail');
};
$inner_text_worker-listen();
};
//?新增加一個(gè)屬性,用來(lái)保存uid到connection的映射
$worker-uidConnections?=?array();
//?當(dāng)有客戶(hù)端發(fā)來(lái)消息時(shí)執(zhí)行的回調(diào)函數(shù)
$worker-onMessage?=?function($connection,?$data)use($worker)
{
//?判斷當(dāng)前客戶(hù)端是否已經(jīng)驗(yàn)證,既是否設(shè)置了uid
if(!isset($connection-uid))
{
//?沒(méi)驗(yàn)證的話(huà)把第一個(gè)包當(dāng)做uid(這里為了方便演示,沒(méi)做真正的驗(yàn)證)
$connection-uid?=?$data;
/*?保存uid到connection的映射,這樣可以方便的通過(guò)uid查找connection,
*?實(shí)現(xiàn)針對(duì)特定uid推送數(shù)據(jù)
*/
$worker-uidConnections[$connection-uid]?=?$connection;
return;
}
};
//?當(dāng)有客戶(hù)端連接斷開(kāi)時(shí)
$worker-onClose?=?function($connection)use($worker)
{
global?$worker;
if(isset($connection-uid))
{
//?連接斷開(kāi)時(shí)刪除映射
unset($worker-uidConnections[$connection-uid]);
}
};
//?向所有驗(yàn)證的用戶(hù)推送數(shù)據(jù)
function?broadcast($message)
{
global?$worker;
foreach($worker-uidConnections?as?$connection)
{
$connection-send($message);
}
}
//?針對(duì)uid推送數(shù)據(jù)
function?sendMessageByUid($uid,?$message)
{
global?$worker;
if(isset($worker-uidConnections[$uid]))
{
$connection?=?$worker-uidConnections[$uid];
$connection-send($message);
return?true;
}
return?false;
}
//?運(yùn)行所有的worker(其實(shí)當(dāng)前只定義了一個(gè))
Worker::runAll();
啟動(dòng)后端服務(wù)
php?push.php?start?-d
前端接收推送的js代碼
var?ws?=?new?WebSocket('ws://127.0.0.1:1234');
ws.onopen?=?function(){
var?uid?=?'uid1';
ws.send(uid);
};
ws.onmessage?=?function(e){
alert(e.data);
};
后端推送消息的代碼
//?建立socket連接到內(nèi)部推送端口
$client?=?stream_socket_client('tcp://127.0.0.1:5678',?$errno,?$errmsg,?1,??STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT);
//?推送的數(shù)據(jù),包含uid字段,表示是給這個(gè)uid推送
$data?=?array('uid'='uid1',?'percent'='88%');
//?發(fā)送數(shù)據(jù),注意5678端口是Text協(xié)議的端口,Text協(xié)議需要在數(shù)據(jù)末尾加上換行符
fwrite($client,?json_encode($data)."\n");
//?讀取推送結(jié)果
echo?fread($client,?8192);
這里的uid不一定是用戶(hù)的id,也可以理解為任務(wù)id即 taskid
以上代碼親測(cè)可以直接使用
1、php+redis 消息隊(duì)列
2、swoole異步執(zhí)行
想玩并發(fā)的話(huà),php 的話(huà)除了 pcntl_fork 多個(gè)進(jìn)程跑腳本,本身有批處理的模塊,可以用 curl_multi_* 批量發(fā)送
一、socket協(xié)議的簡(jiǎn)介
WebSocket是什么,有什么優(yōu)點(diǎn)
WebSocket是一個(gè)持久化的協(xié)議,這是相對(duì)于http非持久化來(lái)說(shuō)的。應(yīng)用層協(xié)議
舉個(gè)簡(jiǎn)單的例子,http1.0的生命周期是以request作為界定的,也就是一個(gè)request,一個(gè)response,對(duì)于http來(lái)說(shuō),本次client與server的會(huì)話(huà)到此結(jié)束;而在http1.1中,稍微有所改進(jìn),即添加了keep-alive,也就是在一個(gè)http連接中可以進(jìn)行多個(gè)request請(qǐng)求和多個(gè)response接受操作。然而在實(shí)時(shí)通信中,并沒(méi)有多大的作用,http只能由client發(fā)起請(qǐng)求,server才能返回信息,即server不能主動(dòng)向client推送信息,無(wú)法滿(mǎn)足實(shí)時(shí)通信的要求。而WebSocket可以進(jìn)行持久化連接,即client只需進(jìn)行一次握手,成功后即可持續(xù)進(jìn)行數(shù)據(jù)通信,值得關(guān)注的是WebSocket實(shí)現(xiàn)client與server之間全雙工通信,即server端有數(shù)據(jù)更新時(shí)可以主動(dòng)推送給client端。
二、介紹client與server之間的socket連接原理
1、下面是一個(gè)演示client和server之間建立WebSocket連接時(shí)握手部分
2、client與server建立socket時(shí)握手的會(huì)話(huà)內(nèi)容,即request與response
a、client建立WebSocket時(shí)向服務(wù)器端請(qǐng)求的信息
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket //告訴服務(wù)器現(xiàn)在發(fā)送的是WebSocket協(xié)議
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== //是一個(gè)Base64 encode的值,這個(gè)是瀏覽器隨機(jī)生成的,用于驗(yàn)證服務(wù)器端返回?cái)?shù)據(jù)是否是WebSocket助理
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin:
b、服務(wù)器獲取到client請(qǐng)求的信息后,根據(jù)WebSocket協(xié)議對(duì)數(shù)據(jù)進(jìn)行處理并返回,其中要對(duì)Sec-WebSocket-Key進(jìn)行加密等操作
HTTP/1.1 101 Switching Protocols
Upgrade: websocket //依然是固定的,告訴客戶(hù)端即將升級(jí)的是Websocket協(xié)議,而不是mozillasocket,lurnarsocket或者shitsocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= //這個(gè)則是經(jīng)過(guò)服務(wù)器確認(rèn),并且加密過(guò)后的 Sec-WebSocket-Key,也就是client要求建立WebSocket驗(yàn)證的憑證
Sec-WebSocket-Protocol: chat
3、socket建立連接原理圖:
三、PHP中建立websocket的過(guò)程講解
SocketService.php:
web.html:
分享標(biāo)題:php多個(gè)用戶(hù)推送數(shù)據(jù),php百萬(wàn)數(shù)據(jù)推送
分享地址:http://muchs.cn/article42/hcjjec.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、微信公眾號(hào)、軟件開(kāi)發(fā)、小程序開(kāi)發(fā)、微信小程序、電子商務(wù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)