Buffer.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <?php
  2. /**
  3. * 二进制协议
  4. *
  5. * struct BufferProtocol
  6. * {
  7. * unsigned char version,//版本
  8. * unsigned short series_id,//序列号 udp协议使用
  9. * unsigned short cmd,//主命令字
  10. * unsigned short sub_cmd,//子命令字
  11. * int code,//返回码
  12. * unsigned int from_uid,//来自用户uid
  13. * unsigned int to_uid,//发往的uid
  14. * unsigned int pack_len,//包长
  15. * char[pack_length-HEAD_LEN] body//包体
  16. * }
  17. *
  18. * @author walkor <worker-man@qq.com>
  19. */
  20. class Buffer
  21. {
  22. /**
  23. * 版本
  24. * @var integer
  25. */
  26. const VERSION = 0x01;
  27. /**
  28. * 包头长度
  29. * @var integer
  30. */
  31. const HEAD_LEN = 23;
  32. /**
  33. * 序列号,防止串包
  34. * @var integer
  35. */
  36. protected static $seriesId = 0;
  37. /**
  38. * 协议头
  39. * @var array
  40. */
  41. public $header = array(
  42. 'version' => self::VERSION,
  43. 'series_id' => 0,
  44. 'cmd' => 0,
  45. 'sub_cmd' => 0,
  46. 'code' => 0,
  47. 'from_uid' => 0,
  48. 'to_uid' => 0,
  49. 'pack_len' => self::HEAD_LEN
  50. );
  51. /**
  52. * 包体
  53. * @var string
  54. */
  55. public $body = '';
  56. /**
  57. * 初始化
  58. * @return void
  59. */
  60. public function __construct($buffer = null)
  61. {
  62. if($buffer)
  63. {
  64. $data = self::bufferToData($buffer);
  65. $this->body = $data['body'];
  66. unset($data['body']);
  67. $this->header = $data;
  68. }
  69. else
  70. {
  71. if(self::$seriesId>=65535)
  72. {
  73. self::$seriesId = 0;
  74. }
  75. else
  76. {
  77. $this->header['series_id'] = self::$seriesId++;
  78. }
  79. }
  80. }
  81. /**
  82. * 判断数据包是否都到了
  83. * @param string $buffer
  84. * @return int int=0数据是完整的 int>0数据不完整,还要继续接收int字节
  85. */
  86. public static function input($buffer, &$data = null)
  87. {
  88. $len = strlen($buffer);
  89. if($len < self::HEAD_LEN)
  90. {
  91. return self::HEAD_LEN - $len;
  92. }
  93. $data = unpack("Cversion/Sseries_id/Scmd/Ssub_cmd/icode/Ifrom_uid/Ito_uid/Ipack_len", $buffer);
  94. if($data['pack_len'] > $len)
  95. {
  96. return $data['pack_len'] - $len;
  97. }
  98. $data['body'] = '';
  99. $body_len = $data['pack_len'] - self::HEAD_LEN;
  100. if($body_len > 0)
  101. {
  102. $data['body'] = substr($buffer, self::HEAD_LEN, $body_len);
  103. }
  104. return 0;
  105. }
  106. /**
  107. * 设置包体
  108. * @param string $body_str
  109. * @return void
  110. */
  111. public function setBody($body_str)
  112. {
  113. $this->body = (string) $body_str;
  114. }
  115. /**
  116. * 获取整个包的buffer
  117. * @param string $data
  118. * @return string
  119. */
  120. public function getBuffer()
  121. {
  122. $this->header['pack_len'] = self::HEAD_LEN + strlen($this->body);
  123. return pack("CSSSiIII", $this->header['version'], $this->header['series_id'], $this->header['cmd'], $this->header['sub_cmd'], $this->header['code'], $this->header['from_uid'], $this->header['to_uid'], $this->header['pack_len']).$this->body;
  124. }
  125. /**
  126. * 从二进制数据转换为数组
  127. * @param string $buffer
  128. * @return array
  129. */
  130. public static function decode($buffer)
  131. {
  132. $data = unpack("Cversion/Sseries_id/Scmd/Ssub_cmd/icode/Ifrom_uid/Ito_uid/Ipack_len", $buffer);
  133. $data['body'] = '';
  134. $body_len = $data['pack_len'] - self::HEAD_LEN;
  135. if($body_len > 0)
  136. {
  137. $data['body'] = substr($buffer, self::HEAD_LEN, $body_len);
  138. }
  139. return $data;
  140. }
  141. }