WebSocket服务端开发(四)-WebSocketServer类socket系列封装函数介绍

本文介绍WebSocketServer类中处理socket的封装函数实现。

getSocketId函数:

function getSocketId($socket) {
  //socketId由socket中的地址和端口号拼接,这样可以保证socket的唯一性,又可以通过id快速读取保存socket的信息以及其附加的其他相关信息
  if (socket_getpeername($socket, $address, $port) === FALSE) {
    return false;
  }
  return $address . '_' . $port;
}

addSocket函数:

function addSocket($socket) {
  //将socket添加到已接受的socket连接池中
  array_push($this->socketList, $socket);
  $socketId = $this->getSocketId($socket);

  //以socketId为索引建立socket映射表,便于后续快速处理socket相关信息
  $this->socketListMap[$socketId] = array(
    //读取缓冲区,由于可能存在分帧的情况,此处统一先保存到缓冲区中,带收到结束帧后统一处理缓冲区
    'buffer' => '',
    //握手成功标识,addSocket在接受连接后调用,故此时并未进行握手,初始化为false
    'handshake' => false,
    //最后通信时间,用于判断超时断开操作
    'lastCommuicate' => time(),
    //socket实例
    'socket' => $socket,
    //错误计数
    'errorCnt' => 0
  );
}

removeSocket函数:

function removeSocket($socketId) {
  $socket = $this->socketListMap[$socketId]['socket'];

  //找出socket在socketList中的索引
  $socketIndex = array_search($socket, $this->socketList);
  if ($this->debug) {
    echo "RemoveSocket at $socketIndex\n";
  }

  //移除socketList中的socket
  array_splice($this->socketList, $socketIndex, 1);

  //移除socketListMap中的相关信息
  unset($this->socketListMap[$socketId]);

  //回调事件
  $this->onAfterRemoveSocket($socketId);
}

socketAccept函数:

function socketAccept() {
  //接受socket
  $socket = socket_accept($this->serverSocket);
  if ($socket !== FALSE) {
    return $socket;
  } else if ($this->debug) {
    echo $this->getLastErrMsg();
  }
}

socketRecv函数:

//从指定socket中读取数据
function socketRecv($socketId) {
  $socket = $this->socketListMap[$socketId]['socket'];
  $bufferLen = socket_get_option($socket, SOL_SOCKET, SO_RCVBUF);
  $recv = socket_recv($socket, $buffer, $bufferLen, 0);
  if ($recv === FALSE) {
    $errCode = $this->getLastErrCode($socketId);
    $this->onerror($errCode, $socketId);
    if ($this->debug) {
      echo $this->getLastErrMsg(null, $errCode);
    }
    return NULL;
  } else if ($recv > 0) {
    if ($this->debug) {
      echo "Recv:\n";
      $this->showData($buffer);
    }
    $this->socketListMap[$socketId]['lastCommuicate'] = time();
  }
  return $buffer;
}

socketSend函数:

function socketSend($socketId, $data) {
  $socket = $this->socketListMap[$socketId]['socket'];
  if ($this->debug) {
    echo "Send:\n";
    $this->showData($data);
  }
  if (socket_write($socket, $data, strlen($data)) > 0) {
    $this->socketListMap[$socketId]['lastCommuicate'] = time();
  }
}

socketClose函数:

function socketClose($socketId) {
  $socket = $this->socketListMap[$socketId]['socket'];
  socket_close($socket);
}

connect函数:

function connect($socket) {
  $this->addSocket($socket);
  $this->onconnected($socket);
}

disconnectBySocket函数:

//此函数通过遍历查找socket信息,性能较低,不建议使用,通常使用disconnect直接根据socketId断开连接
//此函数通常用于一些异常socket的处理
function disconnectBySocket($socket) {
  $socketIndex = array_search($socket, $this->socketList);
  foreach ($this->socketListMap as $socketId => $session) {
    if ($session['socket'] == $socket) {
      $this->disconnect($socketId);
      return;
    }
  }
}

disconnect函数:

function disconnect($socketId, $silent = false) {
  $this->socketClose($socketId);
  if (!$silent) {
    $this->ondisconnected($socketId);
  }
  $this->removeSocket($socketId);
}