Class WebSocketSession

java.lang.Object
dev.relism.flash.websocket.WebSocketSession

public final class WebSocketSession extends Object
Per-connection WebSocket I/O state. One instance per virtual thread.
  • With TCP_NODELAY enabled on the socket (set in HttpServer), Nagle's algorithm is disabled: the kernel sends data as soon as it lands in the send buffer, without waiting. BufferedOutputStream will still batch multiple small writes into one syscall when they happen in the same virtual-thread scheduling quantum — giving us coalescing where it's free, and immediate delivery where it matters.

    The only place an explicit flush is still needed is after the WS handshake (one-time, not on the hot path) and after the CLOSE frame (end of session). Both are handled in close(int) and in HttpServer#performHandshake.

  • Flush on CLOSE frame: close(int) still flushes explicitly because the CLOSE frame is the last thing written before the stream is abandoned — without a flush, the 4 bytes could sit in the buffer forever.

Thread safety

sendText(byte[], int, int), send(byte[], int, int), and close(int) are synchronized on out and safe to call from threads other than the session loop. close(int) uses a CAS on open to guarantee exactly-once CLOSE frame emission under concurrent calls.
  • Constructor Details

    • WebSocketSession

      public WebSocketSession(InputStream in, OutputStream out, int bufferSize)
    • WebSocketSession

      public WebSocketSession(InputStream in, OutputStream out, int bufferSize, Request request, boolean maskOutgoing)
      Parameters:
      request - the HTTP request that upgraded to this session, or null if the caller has no use for it (e.g. a session opened as a WS client rather than accepted as a WS server). Stored as-is, no copy.
      maskOutgoing - true if this session is acting as a WS client — RFC 6455 requires client-to-server frames to be masked, unlike the server-to-client direction writeFrame(byte, byte[], int, int) originally only supported. See writeFrame(byte, byte[], int, int) for how masking is applied without allocating.
  • Method Details

    • isOpen

      public boolean isOpen()
    • closeCode

      public int closeCode()
    • request

      public Request request()
      The request that upgraded this connection, or null — see the 4-arg constructor.
    • isSecure

      public boolean isSecure()
      Whether this connection is TLS (WSS). Delegates to the upgrading request's Request.isSecure() rather than tracking the socket a second time — the request already carries it. false if this session has no backing request (e.g. one opened in WS *client* mode via the 5-arg constructor with request == null).
    • sslSession

      public SSLSession sslSession()
      TLS session for this connection, or null for plain WS or no backing request.
    • sendText

      public void sendText(byte[] utf8, int off, int len) throws IOException
      Throws:
      IOException
    • send

      public void send(byte[] payload, int off, int len) throws IOException
      Throws:
      IOException
    • close

      public void close(int code) throws IOException
      Sends a CLOSE frame exactly once. No flush needed — out is the raw socket OutputStream (not buffered); each write goes directly to the kernel send buffer, and TCP_NODELAY ensures it's transmitted immediately.
      Throws:
      IOException
    • readFrame

      public boolean readFrame(WebSocketFrame frame) throws IOException
      Throws:
      IOException
    • sendPong

      public void sendPong(WebSocketFrame ping) throws IOException
      Throws:
      IOException
    • echo

      public void echo(WebSocketFrame frame) throws IOException
      Throws:
      IOException
    • closeFromPeer

      public void closeFromPeer(WebSocketFrame frame)
    • forceClose

      public void forceClose()