Websocket
MMO\core\server · 1 symbol · generated 30 Sep 2026
Websocket
Websocket.php:22A hand-rolled RFC 6455 WebSocket server: a single instance listens for one TCP connection (listen), performs the HTTP-Upgrade handshake, then exchanges framed messages over it (readMessage/write).
- Namespace
MMO\core\server- Implements
StreamInterface, iRenderable
Index
| MODE_BINARY | ||
| MODE_RAW | ||
| MODE_TEXT | ||
| OP_BINARY | ||
| OP_CLOSE | ||
| OP_CONTINUATION | ||
| OP_PING | ||
| OP_PONG | ||
| OP_TEXT | ||
| WEBSOCKET_KEY | The magic GUID RFC 6455 requires appending to the client's Sec-WebSocket-Key before hashing it into the handshake's Sec-WebSocket-Accept. | |
| address | ||
| closing | ||
| port | ||
| secure | ||
| socket | ||
| stream | ||
| timeout | ||
| close($message, $status) | StreamInterface::close Send a close frame (OP_CLOSE) and wait for the peer's acknowledgment, then release the client stream ($stream) -- always, whether the handshake actually completed o… | |
| connect() | Open the listening server socket ($socket) -- does NOT accept a connection yet (listen for that). | |
| debugName() | ||
| detach() | StreamInterface::detach NOTE: unlike close, does not fclose the resource -- the caller takes ownership and must close it themselves. | |
| disconnect() | Close the client connection (close) and the listening server socket (connect). | |
| eof() | StreamInterface::eof | |
| getContents() | StreamInterface::getContents NOTE: reads raw, unframed bytes from the underlying socket -- not a WebSocket message (readMessage for that). | |
| getMetadata($key) | StreamInterface::getMetadata | |
| getResource() | ||
| getSize() | StreamInterface::getSize | |
| getTimeout() | ||
| getType() | ||
| getUri() | ||
| hasMessage() | Test if stream has awaiting command before calling stream->read. | |
| isConnected() | ||
| isListening() | ||
| isReadable() | StreamInterface::isReadable | |
| isSeekable() | StreamInterface::isSeekable | |
| isWritable() | StreamInterface::isWritable | |
| listen() | Wait for one client to connect (up to setTimeout, or indefinitely) and complete the WebSocket handshake (parses the HTTP Upgrade request's headers, verifies Sec-WebSocket-Key, and replies with… | |
| ping($message) | Send a ping frame (OP_PING); the peer is expected to reply with a pong. | |
| read($length) | StreamInterface::read NOTE: reads raw, unframed bytes from the underlying socket -- not a WebSocket frame/message (readFrame/ | |
| readFrame() | Read and parse one raw WebSocket frame (RFC 6455 section 5.2) from the stream, unmasking its payload if masked. | |
| readLine($length, $ending) | Read line from stream. | |
| readMessage($code) | Read one full WebSocket message, transparently reassembling continuation frames (OP_CONTINUATION) and auto-handling control frames along the way: a ping (OP_PING) gets an automatic pong r… | |
| render($opts) | Get content of socket | |
| rewind() | StreamInterface::rewind | |
| run() | Run the websocket main loop. | |
| seek($offset, $whence) | StreamInterface::seek | |
| setTimeout($timeout) | Set timeout. | |
| Setup($url, $mainFile, $xdebugPort) static | Setup the websocket for a html exchange. | |
| tell() | StreamInterface::tell | |
| Url($address, $port, $secure) static | Generate a valid Javascript url for the websocket | |
| write($data, $mode) | StreamInterface::write A non-string $data is JSON-encoded first (jsonEncode). | |
| writeFrame($code, $payload, $final, $masked) | Write one raw WebSocket frame (RFC 6455 section 5.2): header (opcode/final bit/payload length) plus the (optionally masked) payload. | |
| writeMessage($code, $content, $masked, $framesize) | Write a full WebSocket message, splitting it into multiple frames (writeFrame) if it exceeds $framesize. | |
| __construct($address, $port, $secure) | constructor | |
| __destruct() | Destructor. Closes the stream | |
| __toString() | StreamInterface::__toString |
Constants10
MODE_BINARY
MODE_RAW
- See
write's $mode: write raw bytes with no WebSocket framing (used internally for the handshake and frame bytes themselves).
MODE_TEXT
OP_BINARY
- See
readFrame/writeFrameopcode: a binary message.
OP_CLOSE
- See
readFrame/writeFrameopcode: connection close (close/readMessage's auto-handling).
OP_CONTINUATION
- See
readFrame/writeFrameopcode: a continuation of a fragmented message (writeMessage's multi-frame splitting).
OP_PING
- See
readFrame/writeFrameopcode: ping (ping) --readMessageauto-replies with a pong.
OP_PONG
- See
readFrame/writeFrameopcode: pong, sent automatically byreadMessagein reply to a ping.
OP_TEXT
- See
readFrame/writeFrameopcode: a UTF-8 text message.
WEBSOCKET_KEY
The magic GUID RFC 6455 requires appending to the client's Sec-WebSocket-Key before hashing it into the handshake's Sec-WebSocket-Accept.
Properties7
address
closing
- Type
- bool
port
secure
socket
stream
timeout
Methods39
close($message, $status)
Websocket.php:366StreamInterface::close Send a close frame (OP_CLOSE) and wait for the peer's acknowledgment, then release the client stream ($stream) -- always, whether the handshake actually completed or the peer was already gone (any failure along the way is logged, not thrown -- disconnect/__destruct rely on this never throwing).
connect()
Websocket.php:230Open the listening server socket ($socket) -- does NOT accept a connection yet (listen for that).
| returns | void | |
| throws | if already connected, or the socket couldn't be created (e.g. the port is already in use). |
debugName()
Websocket.php:187| returns | string | e.g. 'socket:localhost:49666'. |
detach()
Websocket.php:408StreamInterface::detach NOTE: unlike close, does not fclose the resource -- the caller takes ownership and must close it themselves.
| returns | mixed | the client stream (now detached from this Websocket), or null if none was connected. |
disconnect()
Websocket.php:314Close the client connection (close) and the listening server socket (connect).
| returns | void |
eof()
Websocket.php:455StreamInterface::eof
| returns | bool | true if no client is connected, or the client stream has reached EOF. |
getContents()
Websocket.php:479StreamInterface::getContents NOTE: reads raw, unframed bytes from the underlying socket -- not a WebSocket message (readMessage for that).
| returns | string | |
| throws | if no client is connected, or reading fails. |
getMetadata($key)
Websocket.php:346StreamInterface::getMetadata
getResource()
Websocket.php:194| returns | the accepted client stream (listen), or null before a client has connected. |
getSize()
Websocket.php:420StreamInterface::getSize
getTimeout()
Websocket.php:222| returns | null | float | the current accept timeout (setTimeout). |
getType()
Websocket.php:354| returns | null | string | the client stream's resource type (e.g. 'stream'), or null if no client is connected (isListening). |
getUri()
Websocket.php:199| returns | string | 'address:port'. |
hasMessage()
Websocket.php:302Test if stream has awaiting command before calling stream->read.
| returns | bool |
isConnected()
Websocket.php:309| returns | bool | whether the listening server socket is open (connect); NOT whether a client is connected (isListening for that). |
isListening()
Websocket.php:292isReadable()
Websocket.php:431StreamInterface::isReadable
| returns | bool | always true. |
isSeekable()
Websocket.php:447StreamInterface::isSeekable
| returns | bool | always false -- a socket cannot be seeked. |
isWritable()
Websocket.php:439StreamInterface::isWritable
| returns | bool | always true. |
listen()
Websocket.php:246Wait for one client to connect (up to setTimeout, or indefinitely) and complete the WebSocket handshake (parses the HTTP Upgrade request's headers, verifies Sec-WebSocket-Key, and replies with 101 Switching Protocols).
ping($message)
Websocket.php:593Send a ping frame (OP_PING); the peer is expected to reply with a pong. @return int bytes written.
read($length)
Websocket.php:535StreamInterface::read NOTE: reads raw, unframed bytes from the underlying socket -- not a WebSocket frame/message (readFrame/
- See
readMessagefor that). Any read failure (timeout, empty read, short read) closes the connection (close, with an appropriate WebSocket status code) before throwing.
| $length | int | exact number of bytes to read. |
| returns | string | exactly $length bytes. |
| throws | if $length is negative. | |
| throws | if the read times out (setTimeout). | |
| throws | if no client is connected, the peer closed the connection, or fewer than $length bytes were read. |
readFrame()
Websocket.php:739Read and parse one raw WebSocket frame (RFC 6455 section 5.2) from the stream, unmasking its payload if masked.
| returns | array | [opcode, payload, final, masked]. |
readLine($length, $ending)
Websocket.php:513Read line from stream.
readMessage($code)
Websocket.php:633Read one full WebSocket message, transparently reassembling continuation frames (OP_CONTINUATION) and auto-handling control frames along the way: a ping (OP_PING) gets an automatic pong reply, and a close frame (OP_CLOSE) is acknowledged (unless this side already initiated the close -- $closing) and ends the connection (closes and nulls $stream directly, without going through close).
render($opts)
Websocket.php:208Get content of socket
rewind()
Websocket.php:494StreamInterface::rewind
| returns | void | |
| throws | always -- a socket cannot be seeked. |
run()
Websocket.php:170Run the websocket main loop. It yields the command that it receives.
| returns | Generator |
seek($offset, $whence)
Websocket.php:502StreamInterface::seek
| $offset | ||
| $whence = SEEK_SET | ||
| returns | void | |
| throws | always -- a socket cannot be seeked. |
setTimeout($timeout)
Websocket.php:216Set timeout.
Setup($url, $mainFile, $xdebugPort)
staticWebsocket.php:128Setup the websocket for a html exchange.
| $url | string | |
| $mainFile = 1 | string | int | the main file to execute when not on command line. if an int, it will look back at the $mainFile trace to find which file need to be executed on the command line |
| $xdebugPort = false | string | bool | if true or a port, will start the script with xdebug (default port for xdebug is 9003) |
| returns | null | self |
tell()
Websocket.php:463StreamInterface::tell
| returns | int | |
| throws | if no client is connected, or the position can't be determined. |
Url($address, $port, $secure)
staticWebsocket.php:92Generate a valid Javascript url for the websocket
write($data, $mode)
Websocket.php:571StreamInterface::write A non-string $data is JSON-encoded first (jsonEncode).
| $data | JsonSerializable | array | string | |
| $mode = self::MODE_TEXT | int | MODE_TEXT/MODE_BINARY (framed as a WebSocket message) or MODE_RAW (raw bytes, no framing). |
| returns | int | the number of bytes written. |
| throws | if no client is connected, or the raw write fails/is incomplete (MODE_RAW). | |
| throws | if $mode isn't one of the MODE_* constants. |
writeFrame($code, $payload, $final, $masked)
Websocket.php:697Write one raw WebSocket frame (RFC 6455 section 5.2): header (opcode/final bit/payload length) plus the (optionally masked) payload.
| $code | int | the opcode (OP_CONTINUATION/OP_TEXT/...). |
| $payload | string | this frame's chunk of the message. |
| $final = false | bool | whether this is the last frame of the message. |
| $masked = true | bool | whether to XOR-mask the payload with a random 4-byte key (as RFC 6455 requires from a client). |
| returns | int | bytes written (verified against a real RFC-6455 frame parser, including the 16-bit extended-length form -- writeMessage's default 4096-byte $framesize keeps individual frames under the 64-bit form's 65535-byte threshold, so that path is exercised only with a $framesize above it). |
writeMessage($code, $content, $masked, $framesize)
Websocket.php:609Write a full WebSocket message, splitting it into multiple frames (writeFrame) if it exceeds $framesize.
| $code | int | an opcode (OP_TEXT/OP_BINARY/OP_CLOSE/OP_PING/OP_PONG). |
| $content | string | the message payload. |
| $masked = true | bool | whether to mask the frame(s) (per RFC 6455, a server should send unmasked frames to a client, but this class defaults to true regardless of which side it's acting as -- masking a server frame is harmless to a spec-compliant client, which unmasks either way). |
| $framesize = 4096 | int | maximum payload bytes per frame; larger content is split across continuation frames (OP_CONTINUATION). |
| returns | int | total bytes written across all frames (verified end-to-end with a 10000-byte message split across multiple frames). |
__construct($address, $port, $secure)
Websocket.php:71constructor
__destruct()
Websocket.php:330Destructor. Closes the stream
__toString()
Websocket.php:337StreamInterface::__toString
| returns | string |