>  기사  >  백엔드 개발  >  PHP에서 소켓 푸시 기술을 구현하는 방법에 대한 예제 설명

PHP에서 소켓 푸시 기술을 구현하는 방법에 대한 예제 설명

jacklove
jacklove원래의
2018-07-05 17:43:361643검색

다음 편집자는 소켓 푸시 기술을 구현한 PHP의 예를 여러분과 공유할 것입니다. 이는 좋은 참고 가치가 있으며 모든 사람에게 도움이 되기를 바랍니다. 에디터를 따라가서 살펴보겠습니다.

소켓이 등장하기 전에도 이미 ajax 예약 요청, 롱 폴링 등의 솔루션이 있었지만 요구 사항을 충족하지 못해 소켓이 탄생했습니다.

socket 기본 기능 소켓

일반적으로 사용되는 소켓 기능 요약

Server: socket_create 소켓 생성 및 기본 매개변수 설정

소켓_bind IP 및 포트 번호 바인딩#🎜 🎜 #

 socket_listen은

socket_accept 클라이언트 연결

socket_read는 클라이언트 데이터를 읽습니다

socket_write는 클라이언트가 데이터를 보냅니다# 🎜🎜## 🎜🎜#   소켓_close 연결 닫기

Client:

socket_create 소켓 생성 및 기본 매개변수 설정#🎜 🎜 # 소켓_연결 연결 소켓 소켓_write 서버로 데이터 보내기

소켓_read 서버 데이터 읽기

소켓_close 연결 닫기

#🎜 🎜 #H5websocket 많지 않음 말하려면 링크로 가세요

좋아요, 코드 게시를 시작해 보세요~

------------ - ---------------------------------선 구분# 🎜 🎜 ## ## ## #####서버 코드 :#### ## ## ## #####
<?php
class WS {
 var $master;
 var $sockets = array();
 var $debug = false;//true为调试模式,输出log日志
 var $handshake = array();
 function __construct($address, $port){
 $this->master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() failed");
 socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1) or die("socket_option() failed");
 socket_bind($this->master, $address, $port)  or die("socket_bind() failed");
 socket_listen($this->master,20)  or die("socket_listen() failed");
 
 $this->sockets[] = $this->master;
 $this->say("Server Started : ".date(&#39;Y-m-d H:i:s&#39;));
 $this->say("Listening on : ".$address." port ".$port);
 $this->say("Master socket : ".$this->master."\n");
 
 while(true){
 $socketArr = $this->sockets;
 $write = NULL;
 $except = NULL;
 socket_select($socketArr, $write, $except, NULL); //自动选择来消息的socket 如果是握手 自动选择主机
 foreach ($socketArr as $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 ($arr as $s){
  $this->send($s, $buffer);
  }
  }
  }
 }
 }
 }
 }
 
 function send($client, $msg){
 $msg = $this->frame($msg);
 socket_write($client, $msg, strlen($msg));
 }
 function connect($socket){
 array_push($this->sockets, $socket);
 $this->say("\n" . $socket . " CONNECTED!");
 $this->say(date("Y-n-d H:i:s"));
 }
 function disConnect($socket){
 $index = array_search($socket, $this->sockets);
 socket_close($socket);
 $this->say($socket . " DISCONNECTED!");
 if ($index >= 0){
 echo &#39;unset index is:&#39;.PHP_EOL;
 unset($this->sockets[$index]);
 }
 }
 function doHandShake($socket, $buffer, $handKey){
 $this->log("\nRequesting handshake...");
 $this->log($buffer);
 list($resource, $host, $origin, $key) = $this->getHeaders($buffer);
 $this->log("Handshaking...");
 $upgrade = "HTTP/1.1 101 Switching Protocol\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("Done handshaking...");
 return true;
 }
 function getHeaders($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]; }
 return array($r, $h, $o, $key);
 }
 function calcKey($key){
 //基于websocket version 13
 $accept = base64_encode(sha1($key . &#39;258EAFA5-E914-47DA-95CA-C5AB0DC85B11&#39;, true));
 return $accept;
 }
 function decode($buffer) {
 $len = $masks = $data = $decoded = null;
 $len = ord($buffer[1]) & 127;
 if ($len === 126) {
 $masks = substr($buffer, 4, 4);
 $data = substr($buffer, 8);
 } 
 else if ($len === 127) {
 $masks = substr($buffer, 10, 4);
 $data = substr($buffer, 14);
 } 
 else {
 $masks = substr($buffer, 2, 4);
 $data = substr($buffer, 6);
 }
 for ($index = 0; $index < strlen($data); $index++) {
 $decoded .= $data[$index] ^ $masks[$index % 4];
 }
 return $decoded;
 }
 function frame($s){
 $a = str_split($s, 125);
 if (count($a) == 1){
 return "\x81" . chr(strlen($a[0])) . $a[0];
 }
 $ns = "";
 foreach ($a as $o){
 $ns .= "\x81" . chr(strlen($o)) . $o;
 }
 return $ns;
 }
 
 function say($msg = ""){
 echo $msg . "\n";
 }
 function log($msg = ""){
 if ($this->debug){
 echo $msg . "\n";
 } 
 }
}
 
new WS(&#39;localhost&#39;, 4000);
#🎜🎜 ## ## 🎜 🎜 🎜#

클라이언트 코드(H5):

<html>
 <head>
 <title>demo</title>
 <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>
 </head>
 <body>
 <input type="text" id="content">
 <input type="button" value="send" id="send">
 <script type="text/javascript">
  var ws = new WebSocket("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);
  })
 </script>
 </body>
</html>
그런 다음 php를 실행합니다. 데모.php를 사용하여 소켓을 엽니다(운영 및 유지 관리에서 트릭을 훔치고 Linux에서 nohup php 데모.php를 실행하면 백그라운드에서 실행될 수 있습니다). 브라우저는 여러 index.html을 열고 통신을 설정할 수 있습니다. .

코드 분석:

1 속성은 각 허용 연결을 저장합니다. 설명이 맞나요?);2. $handshake 배열 속성은 연결이 연결된 상태인지 여부를 저장합니다.

위의 PHP 구현 소켓 예는 다음과 같습니다. 푸시 기술은 편집자가 모든 사람과 공유합니다. 전체 내용은 여기에 있습니다. 참고할 수 있기를 바라며 PHP 중국어 웹 사이트를 지원해 주시기 바랍니다.

당신이 관심을 가질 만한 기사:

php에서 WeChat 공유 배송 주소를 얻는 방법# 🎜🎜 # 클라우드 가상 호스트에 thinkphp5 프로젝트를 배포하는 단계에 대한 자세한 설명

PHPCrawl 크롤러 라이브러리 크롤링 구현 Kugou 재생 목록 방법 설명 예

위 내용은 PHP에서 소켓 푸시 기술을 구현하는 방법에 대한 예제 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.