GatewayProtocol.php 4.0 KB

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