H2S75: How to write a Web.Socket-server, from scratch, in PHP:


Hu: Understanding the difference between Web.Socket-API and Web.Socket-server requires us to be extra-granular<fbno> about the definitions. Typically, when we think of API, which stands for application programming interface, we think of making an HTTP-request, across the public-net, to an external | server, to retrieve some information. However, 1) when we are writing the server, we will be providing an API, for others and 2) when we are also writing the client-code, to call that API, we will be calling our own API.called-port, in the server. This str is exactly | analogous to function def/call, and include called/calling<H2S35> In fact, in our architecture, the Web.Socket-server will behave exactly as an include, called, only when needed. Moreover, this server will be running layered on top of our existing WAMP-install, itself a server, but there is no logical | incoherence here. It’s important to define these terms, and their relationships, before we get started. Wang, post<pg-50>: The fact that WebSocket is a language.agnostic-protocol means you can select any | programming language capable of listening
on a
socket and create a server.

H3S1: Your server must contain a called-function for each API call:

<WP.MIC-H2S66> contains a list of API-calls, supported by Web-Sockets, by default; the client.side-code of your app relies upon making these calls to satisfy client.data-demands, and therefore, you must have the functionality to receive them, any data, and make any returns, in order to have a functioning.API-program.

H3S2: PHP.stream-func,lib:

<php.net>: Streams are the way of generalizing file, network, data compression, and other operations which share a common set of functions and uses. In its simplest definition, a stream is a resource | object which exhibits streamable behavior. That is, it can be read from or written to in a linear fashion<Turing>, and may be able to fseek() to an arbitrary location within the stream. A wrapper is additional | code which tells the stream how to handle specific protocols/encodings. For example, the http wrapper knows how to translate a URL into an HTTP/1.0 | request for a file on a remote | server. A stream is referenced as:

scheme://target 

Hu: In this case, all URLs are stringed representations of the address of a stream, and a pointer<Turing><WP.MIC-H2S41>. Additionally, each file, that makes up your program, is a dormant | stream, that is fread, by default, by the phpinterpreter<WP.MIC-H2S61>, and one can conceive of an internal HTTP-request, or pseudo-request, that is being made, every time that interpreter is called to fget a file, line by line, and echo its content, or execute.<php.net>1) scheme(string) – The name of the wrapper to be used. Examples include: file, http, https, ftp, ftps, compress.zlib, compress.bz2, and php. See Supported Protocols and Wrappers for a list of PHP built-in wrappers. If no wrapper is specified, the function default is used (typically file://). 2) target – Depends on the wrapper used. For filesystem related streams this is typically a path and filename of the desired file. For network related streams this is typically a hostname, often with a path appended. Again, see Supported Protocols and Wrappers for a description of targets for built-in streams. Hu: The implementation of streaming also is reflective of how information must be presented to our brains, in an orderly | way, which is why the best programs contain files that understand the linear | progression of the php-interpreter, and layers the release of information, in coordination with that 1.d-movement, to fit into one’s neurons effectively<ch-42, ch-20, ch-8>. Also important to note that all biological | systems, including coherent | systems created by biological beings, seek selfreplications, and therefore, a programming | language, will seek its own self-recreation, in your mind. Granularly, this means that a programming | language, correctly, will teach you how to write a programming | language, and many of these stream | tutorials, necessary, for building your own interpreter, that can read, and execute, files within a program, or to make files, not of a program, into a program<Turing>

H4S0<fbno>: fseek:

<php.net>: Sets the file position indicator for the file referenced by stream. The new position, measured in bytes from the beginning of the file, is obtained by adding offset to the position | specified by whence. In general, it is allowed to seek past the end-of-file; if data is then written, reads in any unwritten | region between the end-of-file and the sought position will yield bytes with value 0. However, certain streams may not support this behavior, especially when they have an underlying fixed size storage.

fseek(resource $stream, int $offset, int $whence = SEEK_SET): int

1) stream: A file system pointer resource that is typically created using fopen(). Hu: The drive to manifest | efficiency in the conservation of computing resources, in data | delivery, as the simplest | term, is probably what led to the creation of these higherlevel | concepts. Early comp-scientists, working in environments of minimal | resources, likely had to reason maxred | concepts | frequently, and these docs, a historical | reflection.

<?php $fp = fopen('somefile.txt', 'r');
// read some data
$data = fgets($fp, 4096);
// move back to the beginning of the file
// same as rewind($fp);
fseek($fp, 0);?>

H4S1: stream_socket_client:

stream_socket_client(
    string $address,
    int &$error_code = null,
    string &$error_message = null,
    ?float $timeout = null,
    int $flags = STREAM_CLIENT_CONNECT,
    ?resource $context = null
): resource|false

<php.net>, [D, above]: Initiates a stream or datagram connection to the destination specified by address. The type of socket created is determined by the transport specified using standard URL formattingtransport://target. For Internet Domain sockets (AF_INET) such as TCP and UDP, the target portion of the address parameter should consist of a hostname or IP address followed by a colon and a port number. For Unix domain sockets, the target portion should point to the socket file on the filesystem.

H4S2: stream_socket_server:

stream_socket_server(
    string $address,
    int &$error_code = null,
    string &$error_message = null,
    int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
    ?resource $context = null
): resource|false

<php.net>[D]: H5S1: address: The type of socket created is determined by the transport specified using standard URL formatting: transport://target. For Internet Domain sockets (AF_INET) such as TCP and UDP, the target portion of the remote_socket parameter should consist of a hostname or IP address followed by a colon and a port number<WP.MIC-H2S89>. For Unix domain sockets, the target portion should point to the socket file on the filesystem. Depending on the environment, Unix domain sockets may not be available. A list of available transports can be retrieved using stream_get_transports(). See List of Supported Socket Transports for a list of bulitin transports.

H4S3: stream_get_transports:

stream_get_transports(): array

<php.net>: Returns an indexed | array containing the name of all socket transports available on the running system.

H4S4: stream_socket_shutdown:

stream_socket_shutdown(resource $stream, int $mode): bool

<php.net>: Shutdowns (partially or not) a full-duplex connection. H5S1: mode: One of the following constants: STREAM_SHUT_RD (disable further receptions), STREAM_SHUT_WR (disable further transmissions) or STREAM_SHUT_RDWR (disable further receptions and transmissions). H5S2: Returns true on success or false on failure. H5S3: Eg:

<?php
$server = stream_socket_server('tcp://127.0.0.1:1337');
$client = stream_socket_client('tcp://127.0.0.1:1337');

var_dump(fputs($client, "hello"));

stream_socket_shutdown($client, STREAM_SHUT_WR);
var_dump(fputs($client, "hello")); // doesn't work now
?>

Hu: A tad unusual to see stream_socket_server and _client occur in the same script, but I guess the stream-obj is not the script, nor in the script, it’s a specific port that is opened, in connection with a defined socket # Therefore, this is nothing theoretically preventing the script that created this connection, from also opening a connection with it. fputs<self-shill><fbno> is an alias of fwrite<a-r>

H4S5: stream_socket_accept:

stream_socket_accept(resource $socket, ?float $timeout = null, string &$peer_name = null): resource|false

<php.net>: Accept a connection on a socket previously created by stream_socket_server(). H5S1: peer_name Will be set to the name (address) of the client which connected, if included and available from the selected transport. H5S2: Returns a stream to the accepted socket connection or false on failure.

H4S6: stream_socket_recvfrom:

stream_socket_recvfrom(
    resource $socket,
    int $length,
    int $flags = 0,
    ?string &$address = null
): string|false

<php.net>: stream_socket_recvfrom() accepts data from a remote socket up to length bytes. Returns the read data, as a string, or false on failure.

H4S7: stream_socket_sendto:

stream_socket_sendto(
    resource $socket,
    string $data,
    int $flags = 0,
    string $address = ""
): int|false

<php.net>: Sends the specified data through the socket.

H4S8: stream_socket_get_name:

stream_socket_get_name(resource $socket, bool $remote): string|false

<php.net> Returns the local or remote name of a given socket connection. Hu: This function takes $socket, whereas stream_socket_client takes takes $address as an argument. What is the name, relative to these other terms?<php.net>: 1) socket: The socket to get the name of. 2) remote: If set to true the remote socket name will be returned, if set to false the local socket name will be returned. Returns false on failure.

H4S9: Stream_context_create:

<php.net>: Creates and returns a stream context with any options supplied in options preset.

stream_context_create(?array $options = null, ?array $params = null): resource

Hu: Both stream_socket_client/server, and some f-functions, like fopen, take a $context | argument, and stream_context_create is used, to construct this $context, which includes an array of options and parameters.<php.net>: 1): options: Must be an associative array of associative | arrays in the format $arr['wrapper']['option'] = $value, or null. Refer to context options for a list of available | wrappers and options. Defaults to null. 2) params: Must be an associative array in the format $arr[‘parameter’] = $value, or null. Refer to context parameters for a listing of standard stream parameters. Returns a stream context resource.

H4S10: stream_context_set_option

<php.net>: Sets an option on the specified | contextvalue is set to option for wrapper.

stream_context_set_option(
    resource $stream_or_context,
    string $wrapper,
    string $option,
    mixed $value
): bool
stream_context_set_option(resource $stream_or_context, array $options): bool

<php.net>: 1) stream_or_context: The stream or context resource to apply the options to. 2) wrapper: The name of the wrapper (which may be different than the protocol). Refer to context options and parameters for a listing of stream options. 3) option: The name of the option. 4) value: The value of the option. 5) options: The options to set for stream_or_context. H5S1: Separately from set_option, a complementary | function, stream_context_set_params(), can be used to set | params.

H5S2: Socket | context options:

<php.net>:Socket context options are available for all wrappers that work over sockets, like tcphttp and ftp. // cont

H3S3: PHP.socket-func,lib:

<php.net>: The socket | extension implements a low-level interface to the socket communication functions based on the popular BSD sockets<Berkeley sockets b-1983, a-r>, providing the possibility to act as a socket server as well as a client.

H4S1: socket_accept:

<php.net>: After the socket socket has been created using socket_create(), bound to a name with socket_bind(), and told to listen<who?> for connections with socket_listen(), this function will accept incoming connections on that socket. Once a successful | connection is made, a new Socket instance is returned, which may be used for communication

socket_accept(Socket $socket): Socket|false

H4S2: socket_create:

socket_create(int $domain, int $type, int $protocol): Socket|false

<php.net>Creates and returns a Socket instance, also referred to as an endpoint of communication. A typical network connection is made up of 2 sockets, one performing the role of the client, and another performing the role of the server.

Hu: The pronoun | usage patterns, arounds sockets, indicate a pseudo-ephemeral quality, subject-less, almost like the Holy Ghost, a non-existent<#v-t> communication portal, through which data, the Spirit itself, can also transfer. In other words, the socket itself does not exist, and yet, communication is possible through a channel, if it is mutually defined. This notion also defines a protocol, which means that people who speak of it correctly, have to be esoteric. An inherent moral | quest, understanding this<Mark.4-12> escapes those who possess the speck in their eye<Matthew.7-3,5><WP.MIC-H2S80>

H4S3: Socket_read:

<php.net>: socket_read() returns the data as a string on success, or false on error (including if the remote host has closed the connection). 

H4S4: socket_last_error:

<php.net>: If a Socket instance is passed to this function, the last error which occurred on this particular socket is returned. If socket is null, the error code of the last failed socket function is returned. The latter is particularly helpful for functions like socket_create() which don’t return a socket on failure and socket_select() which can fail for reasons not directly tied to a particular socket. The error code is suitable to be fed to socket_strerror() which returns a string describing the given error code.

Param: A Socket instance created with socket_create().

H4S5: socket_strerror:

<php.net>: socket_strerror() takes as its error_code parameter a socket error code as returned by socket_last_error() and returns the corresponding explanatory text.

H4S6: socket_set_block:

<php.net>: The socket_set_block() function removes the O_NONBLOCK flag on the socket specified by the socket parameter. When an operation (e.g. receive, send, connect, accept, …) is performed on a blocking socket, the script will pause its execution until it receives a signal or it can perform the operation.

H4S7: Socket_set_nonblock:

<php.net>: The socket_set_nonblock() function sets the O_NONBLOCK flag on the socket specified by the socket parameter. When an operation (e.g. receive, send, connect, accept, …) is performed on a non-blocking socket, the script will not pause its execution until it receives a signal or it can perform the operation. Rather, if the operation would result in a block, the called function will fail.

H4S8: socket_import_stream:

socket_import_stream(resource $stream): Socket|false

<php.net>: Imports a stream that encapsulates a socket into a socket extension resource.

H4S9: Socket_bind:

H4S10: Socket_write:

<php.net>Returns the number of bytes successfully written to the socket or false on failure. socket_write() does not necessarily write all bytes from the given buffer. It’s valid that, depending on the network buffers etc., only a certain amount of data, even one byte, is written though your buffer is greater. You have to watch out so you don’t unintentionally forget to transmit the rest of your data.

H3S4: PHP.encryption-funct,lib:

// add: https://www.php.net/manual/en/function.sha1.php

https://www.php.net/manual/en/function.base64-encode.php

https://www.php.net/manual/en/function.base64-decode.php

H3S5: Architecture:

Hu<leading-thoughts><fbno>: Try to follow the structure set by php.net as much as possible, for the minds represent an adequately comprehensive meaning of sockets, while using Schweitzer’s code as the tutorial. We can refer to RFC-6455/2616 also. At this time, no other resource can be considered credible. Establish the<php-docs> as the primary | line, and the RFCs as the reference<thought-chitecture!> POST requests are made to specific files, and it’s up to that file to catch the request. It was not intuitive to me initially, but once I was able to render something, I was able to work with it #

H4S1: Core path:

Hu: 1) set up a stream 2) upgrade to Web-Sockets 3) send the payload frame. Theoretically, an equal weight of code should be applied to each, proportionally up from the max-red of 2 lines of code per third #

References:

https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers

https://www.php.net/manual/en/function.stream-socket-client.php

https://www.php.net/manual/en/function.stream-socket-server.php

https://www.php.net/manual/en/function.stream-get-transports.php

https://www.php.net/manual/en/function.stream-socket-accept.php

https://www.php.net/manual/en/function.stream-socket-recvfrom.php

https://www.php.net/manual/en/function.sha1.php

https://www.php.net/manual/en/function.base64-encode.php

https://www.php.net/manual/en/function.base64-decode.php

https://www.php.net/manual/en/function.fputs.php

https://en.wikipedia.org/wiki/Berkeley_sockets

https://www.php.net/manual/en/function.socket-accept.php

https://www.php.net/manual/en/context.php

https://www.php.net/manual/en/function.stream-context-set-params.php

https://www.php.net/manual/en/intro.stream.php

Lengstorf, Jason, and Phil Leggetter. Realtime Web Apps: HTML, Websocket, PHP, and JQuery. Apress.

Wang, Vanessa, et al. HTML5 WebSocket: Build Real-Time Applications w/ HTML5. Apress.

https://www.php.net/manual/en/function.socket-read.php

https://www.php.net/manual/en/function.socket-last-error.php
https://www.php.net/manual/en/function.socket-strerror.php
https://www.php.net/manual/en/function.socket-set-block.php
https://www.php.net/manual/en/function.socket-set-nonblock.php
https://www.php.net/manual/en/function.socket-import-stream.php

https://www.php.net/manual/en/function.socket-write.php


Leave a Reply

Your email address will not be published. Required fields are marked *