GatewayProtocol.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. /**
  3. * This file is part of workerman.
  4. *
  5. * Licensed under The MIT License
  6. * For full copyright and license information, please see the MIT-LICENSE.txt
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @author walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Workerman\Protocols;
  15. /**
  16. * Gateway与Worker间通讯的二进制协议
  17. *
  18. * struct GatewayProtocol
  19. * {
  20. * unsigned int pack_len,
  21. * unsigned char cmd,//命令字
  22. * unsigned int local_ip,
  23. * unsigned short local_port,
  24. * unsigned int client_ip,
  25. * unsigned short client_port,
  26. * unsigned int client_id,
  27. * unsigned char flag,
  28. * unsigned int ext_len,
  29. * char[ext_len] ext_data,
  30. * char[pack_length-HEAD_LEN] body//包体
  31. * }
  32. *
  33. */
  34. class GatewayProtocol
  35. {
  36. // 发给worker,gateway有一个新的连接
  37. const CMD_ON_CONNECTION = 1;
  38. // 发给worker的,客户端有消息
  39. const CMD_ON_MESSAGE = 3;
  40. // 发给worker上的关闭链接事件
  41. const CMD_ON_CLOSE = 4;
  42. // 发给gateway的向单个用户发送数据
  43. const CMD_SEND_TO_ONE = 5;
  44. // 发给gateway的向所有用户发送数据
  45. const CMD_SEND_TO_ALL = 6;
  46. // 发给gateway的踢出用户
  47. const CMD_KICK = 7;
  48. // 发给gateway,通知用户session更改
  49. const CMD_UPDATE_SESSION = 9;
  50. // 获取在线状态
  51. const CMD_GET_ONLINE_STATUS = 10;
  52. // 判断是否在线
  53. const CMD_IS_ONLINE = 11;
  54. // 包体是标量
  55. const FLAG_BODY_IS_SCALAR = 0x01;
  56. /**
  57. * 包头长度
  58. * @var integer
  59. */
  60. const HEAD_LEN = 26;
  61. public static $empty = array(
  62. 'cmd' => 0,
  63. 'local_ip' => '0.0.0.0',
  64. 'local_port' => 0,
  65. 'client_ip' => '0.0.0.0',
  66. 'client_port' => 0,
  67. 'client_id' => 0,
  68. 'flag' => 0,
  69. 'ext_data' => '',
  70. 'body' => '',
  71. );
  72. /**
  73. * 返回包长度
  74. * @param string $buffer
  75. * @return int return current package length
  76. */
  77. public static function input($buffer)
  78. {
  79. if(strlen($buffer) < self::HEAD_LEN)
  80. {
  81. return 0;
  82. }
  83. $data = unpack("Npack_len", $buffer);
  84. return $data['pack_len'];
  85. }
  86. /**
  87. * 获取整个包的buffer
  88. * @param array $data
  89. * @return string
  90. */
  91. public static function encode($data)
  92. {
  93. $flag = (int)is_scalar($data['body']);
  94. if(!$flag)
  95. {
  96. $data['body'] = serialize($data['body']);
  97. }
  98. $ext_len = strlen($data['ext_data']);
  99. $package_len = self::HEAD_LEN + $ext_len + strlen($data['body']);
  100. return pack("NCNnNnNNC", $package_len,
  101. $data['cmd'], ip2long($data['local_ip']),
  102. $data['local_port'], ip2long($data['client_ip']),
  103. $data['client_port'], $data['client_id'],
  104. $ext_len, $flag) . $data['ext_data'] . $data['body'];
  105. }
  106. /**
  107. * 从二进制数据转换为数组
  108. * @param string $buffer
  109. * @return array
  110. */
  111. public static function decode($buffer)
  112. {
  113. $data = unpack("Npack_len/Ccmd/Nlocal_ip/nlocal_port/Nclient_ip/nclient_port/Nclient_id/Next_len/Cflag", $buffer);
  114. $data['local_ip'] = long2ip($data['local_ip']);
  115. $data['client_ip'] = long2ip($data['client_ip']);
  116. if($data['ext_len'] > 0)
  117. {
  118. $data['ext_data'] = substr($buffer, self::HEAD_LEN, $data['ext_len']);
  119. if($data['flag'] & self::FLAG_BODY_IS_SCALAR)
  120. {
  121. $data['body'] = substr($buffer, self::HEAD_LEN + $data['ext_len']);
  122. }
  123. else
  124. {
  125. $data['body'] = unserialize(substr($buffer, self::HEAD_LEN + $data['ext_len']));
  126. }
  127. }
  128. else
  129. {
  130. $data['ext_data'] = '';
  131. if($data['flag'] & self::FLAG_BODY_IS_SCALAR)
  132. {
  133. $data['body'] = substr($buffer, self::HEAD_LEN);
  134. }
  135. else
  136. {
  137. $data['body'] = unserialize(substr($buffer, self::HEAD_LEN));
  138. }
  139. }
  140. return $data;
  141. }
  142. }