php实现socket推送技术的示例
在socket出现之前已经有ajax定时请求、长轮询等方案,但都不能满足需求,socket就应用而生了。
socket基本函数socket
总结下常用的socket函数
服务端:socket_create创建socket设置基本参数
socket_bind绑定ip和端口号
socket_listen监听
socket_accept客户端的连接
socket_read读取客户端的数据
socket_write给单独客户端发送数据
socket_close关闭连接
客户端:socket_create创建socket设置基本参数
socket_connect连接socket
socket_write给服务端发送数据
socket_read读取服务端数据
socket_close关闭连接
H5websocket不多说了,上链接
OK,开始贴代码~
----------------------------------------------------------分割线
服务端代码:
master=socket_create(AF_INET,SOCK_STREAM,SOL_TCP)ordie("socket_create()failed");
socket_set_option($this->master,SOL_SOCKET,SO_REUSEADDR,1)ordie("socket_option()failed");
socket_bind($this->master,$address,$port)ordie("socket_bind()failed");
socket_listen($this->master,20)ordie("socket_listen()failed");
$this->sockets[]=$this->master;
$this->say("ServerStarted:".date('Y-m-dH:i:s'));
$this->say("Listeningon:".$address."port".$port);
$this->say("Mastersocket:".$this->master."\n");
while(true){
$socketArr=$this->sockets;
$write=NULL;
$except=NULL;
socket_select($socketArr,$write,$except,NULL);//自动选择来消息的socket如果是握手自动选择主机
foreach($socketArras$socket){
if($socket==$this->master){//主机
$client=socket_accept($this->master);
if($client<0){
$this->log("socket_accept()failed");
continue;
}else{
$this->connect($client);
}
}else{
$bytes=@socket_recv($socket,$buffer,2048,0);
if($bytes==0){
$this->disConnect($socket);
}
else{
$key=array_search($socket,$this->sockets);
if(empty($this->handshake)||!isset($this->handshake[$key])||!$this->handshake[$key]){
$this->doHandShake($socket,$buffer,$key);
}
else{
$buffer=$this->decode($buffer);
echo$buffer.PHP_EOL;
$key=array_search($socket,$this->sockets);
$arr=$this->sockets;
array_shift($arr);
foreach($arras$s){
$this->send($s,$buffer);
}
}
}
}
}
}
}
functionsend($client,$msg){
$msg=$this->frame($msg);
socket_write($client,$msg,strlen($msg));
}
functionconnect($socket){
array_push($this->sockets,$socket);
$this->say("\n".$socket."CONNECTED!");
$this->say(date("Y-n-dH:i:s"));
}
functiondisConnect($socket){
$index=array_search($socket,$this->sockets);
socket_close($socket);
$this->say($socket."DISCONNECTED!");
if($index>=0){
echo'unsetindexis:'.PHP_EOL;
unset($this->sockets[$index]);
}
}
functiondoHandShake($socket,$buffer,$handKey){
$this->log("\nRequestinghandshake...");
$this->log($buffer);
list($resource,$host,$origin,$key)=$this->getHeaders($buffer);
$this->log("Handshaking...");
$upgrade="HTTP/1.1101SwitchingProtocol\r\n".
"Upgrade:websocket\r\n".
"Connection:Upgrade\r\n".
"Sec-WebSocket-Accept:".$this->calcKey($key)."\r\n\r\n";//必须以两个回车结尾
$this->log($upgrade);
$sent=socket_write($socket,$upgrade,strlen($upgrade));
$this->handshake[$handKey]=true;
$this->log("Donehandshaking...");
returntrue;
}
functiongetHeaders($req){
$r=$h=$o=$key=null;
if(preg_match("/GET(.*)HTTP/",$req,$match)){$r=$match[1];}
if(preg_match("/Host:(.*)\r\n/",$req,$match)){$h=$match[1];}
if(preg_match("/Origin:(.*)\r\n/",$req,$match)){$o=$match[1];}
if(preg_match("/Sec-WebSocket-Key:(.*)\r\n/",$req,$match)){$key=$match[1];}
returnarray($r,$h,$o,$key);
}
functioncalcKey($key){
//基于websocketversion13
$accept=base64_encode(sha1($key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11',true));
return$accept;
}
functiondecode($buffer){
$len=$masks=$data=$decoded=null;
$len=ord($buffer[1])&127;
if($len===126){
$masks=substr($buffer,4,4);
$data=substr($buffer,8);
}
elseif($len===127){
$masks=substr($buffer,10,4);
$data=substr($buffer,14);
}
else{
$masks=substr($buffer,2,4);
$data=substr($buffer,6);
}
for($index=0;$indexdebug){
echo$msg."\n";
}
}
}
newWS('localhost',4000);
客户端代码(H5):
demo varws=newWebSocket("ws://localhost:4000"); ws.onopen=function(){ console.log("握手成功"); } ws.onmessage=function(e){ console.log("message:"+e.data); } ws.onerror=function(){ console.log("error"); } $("#send").click(function(){ content=$("#content").val(); console.log(content); ws.send(content); })
然后执行phpdemo.php开启socket(从运维那偷学一招,linux下执行nohupphpdemo.php&可以在后台执行),浏览器打开多个index.html,就能建立通讯了。
代码解析:
1.属性$sockets数组保存每个accept连接(不知道这么描述对不对);
2.属性$handshake数组保存连接是否在连接状态;
以上这篇php实现socket推送技术的示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。