function onReceive($serv, $fd, $from_id, $data) { if (!isset($this->_buffer[$fd]) or $this->_buffer[$fd] === '') { //超过buffer区的最大长度了 if (count($this->_buffer) >= $this->buffer_maxlen) { $n = 0; foreach ($this->_buffer as $k => $v) { $this->close($k); $n++; //清理完毕 if ($n >= $this->buffer_clear_num) { break; } } $this->log("clear {$n} buffer"); } //解析包头 $header = unpack(self::HEADER_STRUCT, substr($data, 0, self::HEADER_SIZE)); //错误的包头 if ($header === false) { $this->close($fd); } $header['fd'] = $fd; $this->_headers[$fd] = $header; //长度错误 if ($header['length'] - self::HEADER_SIZE > $this->packet_maxlen or strlen($data) > $this->packet_maxlen) { return $this->sendErrorMessage($fd, self::ERR_TOOBIG); } //加入缓存区 $this->_buffer[$fd] = substr($data, self::HEADER_SIZE); } else { $this->_buffer[$fd] .= $data; } //长度不足 if (strlen($this->_buffer[$fd]) < $this->_headers[$fd]['length']) { return true; } //数据解包 $request = self::decode($this->_buffer[$fd], $this->_headers[$fd]['type']); if ($request === false) { $this->sendErrorMessage($fd, self::ERR_UNPACK); } else { //当前请求的头 self::$requestHeader = $_header = $this->_headers[$fd]; //调用端环境变量 if (!empty($request['env'])) { self::$clientEnv = $request['env']; } //socket信息 self::$clientEnv['_socket'] = $this->server->connection_info($header['fd']); $response = $this->call($request, $_header); //发送响应 $ret = $this->server->send($fd, self::encode($response, $_header['type'], $_header['uid'], $_header['serid'])); if ($ret === false) { trigger_error("SendToClient failed. params=" . var_export($request, true) . "\nheaders=" . var_export($_header, true), E_USER_WARNING); } //退出进程 if (self::$stop) { exit(0); } } //清理缓存 unset($this->_buffer[$fd], $this->_headers[$fd]); return true; }
/** * 调用远程函数 * @param $request * @return array */ protected function call($request, $header) { if (empty($request['call'])) { return array('errno' => self::ERR_PARAMS); } //函数不存在 if (!is_callable($request['call'])) { return array('errno' => self::ERR_NOFUNC); } //调用端环境变量 if (!empty($request['env'])) { self::$clientEnv = $request['env']; } //请求头 self::$requestHeader = $header; //socket信息 self::$clientEnv['_socket'] = $this->server->connection_info($header['fd']); $ret = call_user_func_array($request['call'], $request['params']); if ($ret === false) { return array('errno' => self::ERR_CALL); } return array('errno' => 0, 'data' => $ret); }