#!/usr/bin/env php <?php require_once dirname(dirname(__FILE__)) . '/init_env.php'; require_once Da\Sys_App::lib_path("CNsHead.class.php"); $opt = getopt('h::p::', ['2json', '2sp']); $host = isset($opt['h']) ? $opt['h'] : '0.0.0.0'; $port = isset($opt['p']) ? $opt['p'] : '8765'; $socket = stream_socket_server("tcp://{$host}:{$port}", $errno, $errstr); echo 'Listening at port: ' . $port . PHP_EOL; if (!$socket) { echo "{$errstr} ({$errno})\n"; } else { while ($conn = stream_socket_accept($socket, 86400)) { $ns = new NsHead(); $data = $ns->nshead_read($conn); $result = mc_pack_pack2array($data['buf']); isset($opt['2json']) ? print json_encode($result) : (isset($opt['2sp']) ? print serialize($result) : print_r($result)); echo PHP_EOL; $data = ['errno' => 0, 'data' => 'ok']; $body = mc_pack_array2pack($data); $hdr = array('body_len' => strlen($body)); $ns->nshead_write($conn, $hdr, $body); } }
/** * Éú³Éhead buffer */ private function _gen_head_buff() { $body = 'test body'; $body_len = strlen($body); $head = array(); $head['body_len'] = $body_len; $head['magic_num'] = BigpipeCommonDefine::NSHEAD_CHECKSUM_MAGICNUM; $head['reserved'] = BigpipeUtilities::adler32($body); $head_builder = new NsHead(); $head_data = $head_builder->build_nshead($head); $head['magic_num'] = 0; $no_magic_num = $head_builder->build_nshead($head); $head['body_len'] = 0; $bad_head = $head_builder->build_nshead($head); $ret_arr = array('good' => $head_data, 'bad' => $bad_head, 'no_magic' => $no_magic_num); return $ret_arr; }
/** * 解析一条nshead封装的消息 * @return 如果成功,返回收到的nshead body; 如果失败,返回null */ public function receive() { if (null == $this->_socket) { BigpipeLog::warning('[receive error][lose connection with %s:%u]', $this->_target['socket_address'], $this->_target['socket_port']); return null; // 无连接 } $res = array(); $buff = $this->_socket->read(36); // 读取一个nshead头 BigpipeLog::debug("[receive nshead][{$buff}]"); if (empty($buff) || strlen($buff) < 36) { $buff_size = strlen($buff); BigpipeLog::warning("[receive nshead error][head_size:{$buff_size}]"); return null; } $nshead = new NsHead(); $res['head'] = $nshead->split_nshead($buff, false); $is_ok = false; $err_msg = null; do { // 读取nshead // 下述判断理论上到不了 $res_head = $res['head']; if (false === $res_head) { $err_msg = '[fail to read head]'; break; } if (!isset($res_head['body_len']) || 0 == $res_head['body_len']) { // 不可能有size为0的包 $err_msg = '[no body_len]'; break; } //读取数据包内容 $res['body'] = $this->_socket->read($res_head['body_len']); if (false === $res['body']) { $err_msg = '[no message body]'; break; } if (true === $this->_check_frame) { // 整包校验 if (BigpipeCommonDefine::NSHEAD_CHECKSUM_MAGICNUM != $res_head['magic_num']) { // 包不带checksum也没问题,但是要打印日志追一下 BigpipeLog::debug('[receive][frame does not have checksum, skip checksum]'); } else { // checksum在nshead, reserved字段中 $checksum = BigpipeUtilities::adler32($res['body']); if ($res_head['reserved'] != $checksum) { $err_msg = sprintf('[checksum failed][send:%u][recv:%u]', $res_head['reserved'], $checksum); $res['body'] = null; break; // 校验失败,丢弃包 } } } // end of check frame integerity $is_ok = true; } while (false); // 用于分支检测 if (!$is_ok) { // 打印错误日志 BigpipeLog::warning("[receive][frame error]%s", $err_msg); return null; } return $res['body']; }