ホームページ >バックエンド開発 >PHPチュートリアル >protobuf-phpとソケットの使い方
この記事では、protobuf-php とソケットの使用方法を主にコードの形式で説明します。
vi login.proto
package login; message ReqCheckVerifyVerLoginClient { required int32 game = 1; ///< 游戏类型编号 required bytes version = 2; ///< 游戏版本号} message AnsCheckVerifyVerLoginClient { required uint32 ret_code = 1; //返回码 optional uint32 forbid_flag = 2; //冻结时间 optional uint32 time_diff = 3; //剩余解封时间}
protoc --plugin=/usr/local/php/bin/protoc-gen-php --php_out=. -I.login.proto
login.php
namespace login { class ReqCheckVerifyVerLoginClient extends \DrSlump\Protobuf\Message { /** @var int */ public $game = null; /** @var string */ public $version = null; /** @var \Closure[] */ protected static $__extensions = array();.........
を使用.php
function.php
<?php/** * Created by PhpStorm. * User: Administrator * Date: 2018/3/23 * Time: 19:26 */require 'socket.php';require 'structNum.php';function socket($ip,$port,$packed){ try{ $socket = Socket::singleton(); $socket->connect($ip,$port); if(count($packed) >1){ foreach ($packed as $key){ $sockResult = $socket->sendRequest($key);// 将包发送给服务器 sleep(3); } } $getrepost = $socket->getResponse(); $socket->disconnect (); //关闭链接 } catch (Exception $e) { var_dump($e); $this->log_error(" error send to server".$e->getMessage()); } return $getrepost; }function unPackData($data){ $rev_len = unpack("L*",substr($data,0,4)); $rev_num = unpack("S*",substr($data,4,2)); $rev_data = substr($data,6,2); $data_array = array( 'num' =>$rev_num, 'data'=>$rev_data ); return $data_array; } $structNum;function StructNum($num){ $class = $GLOBALS['structNum'][$num]; return $class; }
socket.php
<?phpdefine("CONNECTED", true); define("DISCONNECTED", false); Class Socket { private static $instance; private $connection = null; private $connectionState = DISCONNECTED; private $defaultHost = "192.168.128.198"; private $defaultPort = 9301; private $defaultTimeOut = 60; public $debug = false; public function __construct() { } /** * Singleton pattern. Returns the same instance to all callers * * @return Socket */ public static function singleton() { if (self::$instance == null || ! self::$instance instanceof Socket) { self::$instance = new Socket(); } return self::$instance; } public function connect($serverHost=false,$serverPort=false,$timeOut=false) { if($serverHost == false) { $serverHost = $this->defaultHost; } if($serverPort == false) { $serverPort = $this->defaultPort; } $this->defaultHost = $serverHost; $this->defaultPort = $serverPort; if($timeOut == false) { $timeOut = $this->defaultTimeOut; } $this->connection = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if(socket_connect($this->connection,$serverHost,$serverPort) == false) { $errorString = socket_strerror(socket_last_error($this->connection)); $this->_throwError("Connecting to {$serverHost}:{$serverPort} failed.<br>Reason: {$errorString}"); }else{ $this->_throwMsg("Socket connected!"); } $this->connectionState = CONNECTED; } /** * Disconnects from the server * * @return True on succes, false if the connection was already closed */ public function disconnect() { if($this->validateConnection()) { socket_close($this->connection); $this->connectionState = DISCONNECTED; $this->_throwMsg("Socket disconnected!"); return true; } return false; } public function sendRequest($data) { if($this->validateConnection()) { $result = socket_write($this->connection,$data,strlen($data)); return $result; }else{ $this->_throwError("Sending command \"{$data}\" failed.<br>Reason: Not connected"); } } public function getResponse() { if($this->validateConnection()) { if( ($ret = socket_read($this->connection,8192)) == false){ $this->_throwError("Receiving response from server failed.<br>Reason: Not bytes to read"); return false; } else{ return $ret; } } } public function isConn() { return $this->connectionState; } public function getUnreadBytes() { $info = socket_get_status($this->connection); return $info['unread_bytes']; } public function getConnName(&$addr, &$port) { if ($this->validateConnection()) { socket_getsockname($this->connection,$addr,$port); } } public function waitForResponse() { if($this->validateConnection()) { return socket_read($this->connection, 2048); } $this->_throwError("Receiving response from server failed.<br>Reason: Not connected"); return false; } /** * Validates the connection state * * @return bool */ private function validateConnection() { return (is_resource($this->connection) && ($this->connectionState != DISCONNECTED)); } /** * Throws an error * * @return void */ private function _throwError($errorMessage) { echo "Socket error: " . $errorMessage; } /** * Throws an message * * @return void */ private function _throwMsg($msg) { if ($this->debug) { echo "Socket message: " . $msg . "\n\n"; } } /** * If there still was a connection alive, disconnect it */ public function __destruct() { $this->disconnect(); } }
structNum.php // クラスの辞書
<?php/** * Created by PhpStorm. * User: Administrator * Date: 2018/3/26 * Time: 17:54 */$structNum = array( 46=>new \login\ReqCheckVerifyVerLoginClient(), 47=>new \login\AnsCheckVerifyVerLoginClient(), );
vi use_login.php
<?php/** * Created by PhpStorm. * User: Administrator * Date: 2018/3/26 * Time: 15:20 */require_once 'DrSlump/Protobuf.php'; \DrSlump\Protobuf::autoload();require 'login.php';require 'function.php';//实例化 class 46$login = StructNum(46); $login->setGame(3); $login->setVersion('0.0.1'); $first_data = pack("I*",24063);//一个可识别的ID $first_len = pack("I*",4); $second_data = $login->serialize();//序列化 $second_len = pack("I*",strlen($second_data) + 2); $second_num = substr(pack("I*",46),0,2); $first_pack = $first_len.$first_data; //字节 包体 $second_pack = $second_len.$second_num.$second_data;//长度 协议 内容(protobuf) $port = 9301; $ip = "192.168.128.198"; $pack = array($first_pack,$second_pack); $result = socket($ip,$port,$pack);//连接 发送 接受数据 数据为长度 协议 内容(protobuf) $unPackDatas = unPackData($result);//拆分数据(按需拆分) 按 4 2 2 拆分//实例化 class 46$reLogin = StructNum($unPackDatas['num'][1]); $reLogin->parse($unPackDatas['data']);//拆分后的内容 再反序列化 $reLogin->getRetCode(); $reLogin->getForbidFlag(); $reLogin->clearTimeDiff(); var_dump($reLogin);
関連する推奨事項:
におけるソケット通信の詳細な説明PHP Socketサーバーの構築とテスト例の共有
以上がprotobuf-phpとソケットの使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。