{@inheritdoc}

@throws NodeDisconnectException
@throws WebSocketException WebSocketClient provided invalid closing code or whole payload
341276
protected function handleClientCloseFrame(NetworkFrame $frame)
    {
        $this->logger->debug("Client sent close frame, parsing");

        //TODO strict
        $code = $frame->getPayloadPart(0, 2);

        if (!empty($code)) { //Code is optional BUT it can't be 0
            if (!isset($code[1])) { // payload have to be at least 2 bytes
                throw new WebSocketException("Invalid closing payload", DataFrame::CODE_PROTOCOL_ERROR);
            }

            $code = unpack("n", $code);
            $code = $code[1]; //Array dereference on call is allowed from 5.4
            $this->logger->debug("Client disconnected with code: " . $code);

            if (!DataFrame::validateCloseCode($code)) {
                throw new WebSocketException("Invalid close code", DataFrame::CODE_PROTOCOL_ERROR);
            }

            if (!mb_check_encoding($frame->getPayloadPart(2), 'UTF-8')) {
                throw new WebSocketException("Close frame payload is not valid UTF-8",
                    NetworkFrame::CODE_DATA_TYPE_INCONSISTENT);
            }
        }

        $this->logger->debug("Converting client close frame into server close frame");
        $frame->setOpcode(DataFrame::OPCODE_CLOSE);
        $frame->setMasking(false);
        $frame->setPayload(pack("n", DataFrame::CODE_CLOSE_NORMAL) . "Client closed connection");
        $this->pushData($frame);
        $this->disconnect();
    }
769235
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
        if (frame instanceof CloseWebSocketFrame) {
            this.handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain());
            CompletableFuture.completedFuture(new WebSocketContext(this.session,this.handler))
                    .thenAcceptAsync(this.handler::onDisConnect);
            return;
        }
        if (frame instanceof PingWebSocketFrame) {
            ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
            return;
        }

        if (!(frame instanceof TextWebSocketFrame)) {
            throw new UnsupportedOperationException("unsupported frame type: " + frame.getClass().getName());
        }
        CompletableFuture.completedFuture(new WebSocketContext(this.session,this.handler,((TextWebSocketFrame) frame).text()))
                .thenAcceptAsync(this.handler::onText,ctx.executor());
    }
125378
public function close()
    {
        try {
            $this->socket->disconnect($this->dsn);
        } catch (\ZMQException $e) {
            throw new ClientException($e->getMessage());
        }
    }
69399
AmqpClient closeOkConnection(Continuation callback, ErrorHandler error) {
        Object[] args = {};
        AmqpBuffer bodyArg = null;

        String methodName = "closeOkConnection";
        String methodId = "10" + "50";
        AmqpMethod amqpMethod = MethodLookup.LookupMethod(methodId);
        Object[] arguments = {this, amqpMethod, this.id, args, bodyArg};
        asyncClient.enqueueAction(methodName, "write", arguments, callback, error);
        return this;
    }
983054
public void closeAsync() throws IOException {
        if (anyAreSet(state, FLAG_CLOSED) || servletRequestContext.getOriginalResponse().isTreatAsCommitted()) {
            return;
        }
        if (!servletRequestContext.getExchange().isInIoThread()) {
            servletRequestContext.getExchange().getIoThread().execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        closeAsync();
                    } catch (IOException e) {
                        UndertowLogger.REQUEST_IO_LOGGER.closeAsyncFailed(e);
                    }
                }
            });
            return;
        }
        try {

            setFlags(FLAG_CLOSED);
            clearFlags(FLAG_READY);
            if (allAreClear(state, FLAG_WRITE_STARTED) && channel == null) {

                if (servletRequestContext.getOriginalResponse().getHeader(Headers.TRANSFER_ENCODING_STRING) == null) {
                    if (buffer == null) {
                        servletRequestContext.getOriginalResponse().setHeader(Headers.CONTENT_LENGTH, "0");
                    } else {
                        servletRequestContext.getOriginalResponse().setHeader(Headers.CONTENT_LENGTH, Integer.toString(buffer.position()));
                    }
                }
            }
            createChannel();
            if (buffer != null) {
                if (!flushBufferAsync(true)) {
                    return;
                }

                if (pooledBuffer != null) {
                    pooledBuffer.close();
                    buffer = null;
                } else {
                    buffer = null;
                }
            }
            channel.shutdownWrites();
            setFlags(FLAG_DELEGATE_SHUTDOWN);
            if (!channel.flush()) {
                channel.resumeWrites();
            }
        } catch (IOException | RuntimeException | Error e) {
            if (pooledBuffer != null) {
                pooledBuffer.close();
                pooledBuffer = null;
                buffer = null;
            }
            throw e;
        }
    }
258248
function socketOnEnd() {
  const websocket = this[kWebSocket];

  websocket.readyState = WebSocket.CLOSING;
  websocket._receiver.end();
  this.end();
}
663738
@Override
    public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        TioWebsocketMethodMapper onClose = methods.getOnClose();
        if (onClose != null) {
            onClose.getMethod().invoke(onClose.getInstance(), channelContext);
        }
        log.debug("onClose");
        Tio.remove(channelContext, "onClose");
        return null;
    }
914303
function socketOnClose() {
  const websocket = this[kWebSocket];

  this.removeListener('close', socketOnClose);
  this.removeListener('end', socketOnEnd);

  websocket.readyState = WebSocket.CLOSING;

  //
  // The close frame might not have been received or the `'end'` event emitted,
  // for example, if the socket was destroyed due to an error. Ensure that the
  // `receiver` stream is closed after writing any remaining buffered data to
  // it. If the readable side of the socket is in flowing mode then there is no
  // buffered data as everything has been already written and `readable.read()`
  // will return `null`. If instead, the socket is paused, any possible buffered
  // data will be read as a single chunk and emitted synchronously in a single
  // `'data'` event.
  //
  websocket._socket.read();
  websocket._receiver.end();

  this.removeListener('data', socketOnData);
  this[kWebSocket] = undefined;

  clearTimeout(websocket._closeTimer);

  if (
    websocket._receiver._writableState.finished ||
    websocket._receiver._writableState.errorEmitted
  ) {
    websocket.emitClose();
  } else {
    websocket._receiver.on('error', receiverOnFinish);
    websocket._receiver.on('finish', receiverOnFinish);
  }
}
470183
@Override
    public void closeConnection() throws JdbcServerException {
        if (!endpointConfiguration.isAutoConnect()) {
            handleMessageAndCheckResponse(JdbcMessage.closeConnection());
        }

        if (connections.decrementAndGet() < 0) {
            connections.set(0);
        }
    }
1234067
private void closeOutgoingSockets() throws ClientException {

        SocketOperator op = new SocketOperator() {
                public void operate(SocketBox sb) throws Exception {
                    if (((ManagedSocketBox) sb).isReusable()) {
                        Socket s = sb.getSocket();
                        if (s != null) {
                            // write the closing Eblock and close the socket
                            EBlockImageDCWriter.close(
                                  new DataOutputStream(s.getOutputStream()));
                        }
                    }
                }
       };

        try {
            socketPool.applyToAll(op);
        } catch (IOException e) {
            // ignore - sometimes server might close the socket
        } catch (Exception e) {
            ClientException ce =
                new ClientException(ClientException.SOCKET_OP_FAILED);
            ce.setRootCause(e);
            throw ce;
        }
    }
92380
function opcodeSwitch($client_id, &$ws)
    {
        $this->log("[$client_id] opcode={$ws['opcode']}");

        switch($ws['opcode'])
        {
            //data frame
            case self::OPCODE_BINARY_FRAME:
            case self::OPCODE_TEXT_FRAME:
                if (0x1 === $ws['fin'])
                {
                    $this->onMessage($client_id, $ws);
                }
                else
                {
                    $this->log("not finish frame");
                }
                break;

            //heartbeat
            case self::OPCODE_PING:
                $message = &$ws['message'];
                if (0x0  === $ws['fin'] or 0x7d  <  $ws['length'])
                {
                    $this->close($client_id, self::CLOSE_PROTOCOL_ERROR, "ping error");
                    break;
                }
                $this->connections[$client_id]['time'] = time();
                $this->send($client_id, $message, self::OPCODE_PONG, true);
                break;

            case self::OPCODE_PONG:
                if (0 === $ws['fin'])
                {
                    $this->close($client_id, self::CLOSE_PROTOCOL_ERROR, "pong? server cannot pong.");
                }
                break;

            //close the connection
            case self::OPCODE_CONNECTION_CLOSE:
                $length = &$ws['length'];
                if (1 === $length or 0x7d < $length)
                {
                    $this->close($client_id, self::CLOSE_PROTOCOL_ERROR, "client active close");
                    break;
                }

                if ($length > 0)
                {
                    $message = $ws['message'];
                    $_code   = unpack('nc', substr($message, 0, 2));
                    $code    = $_code['c'];

                    if ($length > 2)
                    {
                        $reason = substr($message, 2);
                        if (false === (bool) preg_match('//u', $reason))
                        {
                            $this->close($client_id, self::CLOSE_MESSAGE_ERROR);
                            break;
                        }
                    }

                    if (1000 > $code || (1004 <= $code && $code <= 1006) || (1012 <= $code && $code <= 1016) || 5000  <= $code)
                    {
                        $this->close($client_id, self::CLOSE_PROTOCOL_ERROR);
                        break;
                    }
                    else
                    {
                        $this->close($client_id, self::CLOSE_PROTOCOL_ERROR, "client active close, code={$code}");
                        break;
                    }
                }
                break;
            default:
                $this->close($client_id, self::CLOSE_PROTOCOL_ERROR, "unkown websocket opcode[{$ws['opcode']}]");
                break;
        }
        unset($this->frame_list[$client_id]);
    }
887254
@Override
  public void close()
    throws IOException
  {
    SocketChannel s = _channel;
    _channel = null;
    
    SSLSocket sslSocket = _sslSocket;
    _sslSocket = null;

    if (sslSocket != null) {
      try {
        sslSocket.close();
      } catch (Exception e) {
      }
    }

    if (s != null) {
      try {
        s.close();
      } catch (Exception e) {
      }
    }
  }
779478
public static void sendClose(final ByteBuffer data, final WebSocketChannel wsChannel, final WebSocketCallback<Void> callback) {
        CloseMessage sm = new CloseMessage(data);
        sendClose(sm, wsChannel, callback);
    }
215150
AmqpClient closeConnection(int replyCode, String replyText, int classId, int methodId1) {
        this.closeConnection(replyCode, replyText, classId, methodId1, null, null);
        return this;
    }
421282
@Override
    public CompletableFuture<Integer> forceCloseWebSocket(Serializable userid, @RpcTargetAddress InetSocketAddress targetAddress) {
        //不能从sncpNodeAddresses中移除，因为engine.forceCloseWebSocket 会调用到disconnect
        if (logger.isLoggable(Level.FINEST)) logger.finest(WebSocketNodeService.class.getSimpleName() + ".event: " + userid + " forceCloseWebSocket from " + targetAddress);
        if (localEngine == null) return CompletableFuture.completedFuture(0);
        return CompletableFuture.completedFuture(localEngine.forceCloseLocalWebSocket(userid));
    }
932688
function wrapNodeSocket(ws, reportError) {
  // Data traveling from websocket to consumer
  var incoming = makeChannel();
  // Data traveling from consumer to websocket
  var outgoing = makeChannel();

  onTake = wrapHandler(onTake, onError);
  outgoing.take(onTake);

  ws.onerror = onError;
  ws.onmessage = wrap(onMessage, onError);
  ws.onclose = wrap(onClose, onError);

  function onError(err) {
    if (reportError) return reportError(err);
    console.error(err.stack);
  }

  function onMessage(evt) {
    if (evt.data instanceof ArrayBuffer) {
      incoming.put(new Uint8Array(evt.data));
    }
  }

  function onClose(evt) {
    incoming.put();
  }

  function onTake(data) {
    // console.log("TAKE", data);
    if (data === undefined) {
      ws.close();
      return;
    }
    ws.send(data);
    outgoing.take(onTake);
  }

  return {
    put: outgoing.put,
    drain: outgoing.drain,
    take: incoming.take,
  };
}
370687
@Override
    public void close() throws InterruptedException {
        if (m_blessedThreadIds.contains(Thread.currentThread().getId())) {
            throw new RuntimeException("Can't invoke backpressureBarrier from within the client callback thread " +
                    " without deadlocking the client library");
        }
        m_isShutdown = true;
        synchronized (m_backpressureLock) {
            m_backpressureLock.notifyAll();
        }

        if (m_reconnectStatusListener != null) {
            m_distributer.removeClientStatusListener(m_reconnectStatusListener);
            m_reconnectStatusListener.close();
        }

        if (m_ex != null) {
            m_ex.shutdown();
            if (CoreUtils.isJunitTest()) {
                m_ex.awaitTermination(1, TimeUnit.SECONDS);
            } else {
                m_ex.awaitTermination(365, TimeUnit.DAYS);
            }
        }
        m_distributer.shutdown();
        ClientFactory.decreaseClientNum();
    }