Esempio n. 1
0
#!/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'];
 }