Last Updated:

Websocket | How to manage them in PHP

Websocket in php

At a time when the Internet was widely used around the world, it was a well-built model consisting of hardware and software. Such a global network remains to this day. However, the seven-level OSI model was replenished with a new protocol "ws", which became part of the application layer, in which its close relative, the http protocol, is located.

Developing real-time applications requires slightly different behavior from the request/response procedure between the client and the server. Web applications that work in real time include: chats, instant messengers, online games.

In short, those resources whose functioning is based on events. The user does not just read or view the content, but constantly accesses the server. Such calls can be tens of thousands and millions per second – it all depends on how many customers are currently using the application.

 

Over the HTTP protocol, during the application session in real time, the client constantly accesses the server. This is accompanied by voluminous headers for data packets and significant loads on the server and traffic.

 

When using a socket, the client machine asks a question like: Are there any messages? (client), none (response from the server). This happens in the background, invisible to the user. That is, at a certain frequency per second, the client asks the server for data, and the server machine sends a "no" response until the other client sends the message.

This behavior model is suitable for creating applications in real time and the server in this case does not experience a serious load. Therefore, some time after the approval of HTTP, web sockets were invented, which significantly reduced the load on the server. After all, the Internet became available to everyone, and web applications were constantly being improved. We needed a technology that reduced the cost of maintaining the application. In its place was the WS protocol.

What are web sockets?

A web socket is an application layer protocol of the TCP/IP stack of the seven-tier OSI model. The main protocols of the application layer before the advent of sockets:

  • HTTP,
  • HTTPS,
  • DNS,
  • FTP.

The socket protocol has the abbreviation WS and WSS for secure connection, similar to HTTPS. Sockets use the TCP protocol to transfer data at the transport layer.

Sockets (WS protocol) are a brethrene of HTTP because they perform the same function of transferring data from the client to the server. However, these two protocols differ in the principle of client/server interaction. The technology of socket functioning has just found its application in real-time applications. Before they existed, developers found solutions using HTTP. But this protocol was not effective for the development of such applications.

Disadvantages of web sockets

In order for developers to manage and configure the operation of the WS protocol, in the browser and on the server, web sockets are objects with their own properties and methods. PHP has a number of functions that allow you to control the behavior of sockets. The same applies to JavaScript – the client language also allows you to manipulate server technology.

The main disadvantages of sockets are the fact that the Web-socket object is not supported by all browsers. Legacy browsers are not equipped with this object in the DOM, as well as outdated versions of server software, and also do not support the ability to send requests and responses via WS.

Learn more about how sockets work

The specification for web sockets defines separate APIs for client-to-server connectivity. During the session, the connection occurs once and lasts constantly until the end of the session. The client and server are constantly waiting, while they are connected to each other. The client and server can send data to each other at any time — this does not require a new connection, as when using HTTP.

The client establishes a connection with the server, which reciprocates - this can be expressed in a handshake:

  1. The client sends an HTTP request with an additional upgrade header that tells you that the connection should be established over a socket.
  2. The server accepts the request and sends the response over HTTP with the same additional header.
  3. A handshake is made and now a permanent connection is maintained between the client and the server for the duration of the socket session.
  4. The basis for such a connection is TCP/IP.
  5. The client and server can communicate bypassing HTTP.
  6. Of course, the exchange can be carried out via HTTP.
  7. The bottom line is that one functionality of the application works with sockets, the other with HTTP.

The header of the request from the client is as follows:

  • GET/POST ws://mediacontent.buisness.com/ HTTP/1.1 — a standard HTTP header that is generated through the URL of the request;
  • Origin: http://buisness.com — Describes the protocol, domain and port to which the request is sent;
  • Connection: Upgrade — indicates that the browser wants to establish a connection via socket;
  • Host: mediacontent.buisness.com - Specifies the name of the server.
  • Upgrade: websocket is a connection protocol.
  • Sec-WebSocket-Key: Iv8op/8s+lYFgNBcXmNP8Q= — secure connection key that allows the browser to verify that the response is intended for it;

Response header sent by the server:

  • HTTP/1.1 101 Switching Protocols;
  • Date: Fri, 12 Oct 2020 10:37:20 GMT;
  • Connection: Upgrade;
  • Upgrade: WebSocket;
  • Sec-WebSocket-Accept: hhFluiDokk24srzEOFBUlVSlC2g=== — secure connection key that allows the browser to verify that the response is intended for it;
  • Sec-WebSocket-Version: 13 — версия протокола.

After the connection between the client and the server is established, the data transfer is carried out via the WS protocol, bypassing HTTP. At the same time, the connection is maintained constantly until the window is closed (the end of the session).

Depending on the version of the server, browser or script complexity, additional headers may be sent:

Sec-WebSocket-Extensions: deflate-frame. Indicates that the browser supports compression for data. If the WebSocket object is modified to refer to the latest versions of browsers, then the headers are also extended. This header sends information about which extensions the browser supports.

Sec-WebSocket-Protocol: soap, wamp. The browser warns the server that not only standard data will be sent, but also data that supports soap and WAMP protocols. The header describes the format of the data that the client and server will send to each other. The values of these headers are not set automatically, but the constructor call is passed:

new WebSocket(«wss://localhost», [«soap», «wamp»]).

Data transfer via socket connection

In HTTP, data is transmitted in packets. After a request from the client, HTTP sends out text or image data through small pieces. When all the pieces are collected on the client's computer, the user sees a full-fledged web page, text or image. Each such packet is provided with a header similar to those we considered earlier. That is: how many packets - so many headers.

In a socket connection, the data transfer technology is slightly different. Data is transmitted not in packets, but in frames. Each such frame is provided with a header, but of a different format. At the same time, the frame can be provided with both text data and binary data.

Some features and benefits of frames include:

  1. The headers are different from HTTP and are much smaller in format.
  2. The overhead for transporting data is lower than through HTTP.
  3. A small amount of data is placed in a single frame.
  4. A large amount of data is fragmented into multiple frames.

Frames transmit three types of information: text data (UTF-8), binary data, and control frames for opening, maintaining, and closing a connection.

The WS protocol supports the entire WAN structure that HTTP supports. Therefore, to connect via WS, you do not need to change any settings, or install additional software. However, you must make sure that the server and browser support sockets.

Check your browser's socket support

Any browser has a JavaScript console. Through the console, you should check for the necessary JavaScript core objects, as well as the DOM.

This is done in the following order:

  1. Open the browser;
  2. Open developer tools;
  3. Select Console;
  4. Enter the WebSocket command and press Enter;
  5. If the WebSocket constructor function is displayed, the object is supported by the browser;
  6. If Undefined is displayed instead of a constructor, there is no such object.

Creating a socket server in PHP

The first thing to do is to configure the server to work with web sockets. To do this, find the php file.ini, uncomment the line "extension = php_sockets.dll" and restart the server. The same should be done on the hosting, if any.

In order to be able to use sockets in a web application, you need to create a special script in PHP on the server. This script allows you to create a socket server that will create a server-side connection if necessary.

Example: Create a socket server script and write it to the file "socet.php"

function LoadSocketServer($limit = 0) { // Function that starts a server that is running for a certain time "limit"
$time_to_start = time(); // Time to start the echo server
'SERVER START TO WORK'; // Output to the console notification when the server starts

echo 'Socket was created';
$socketObject = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); Create a socket object:
if (!$socketObject) {
die('Error: ' . socket_strerror(socket_last_error())); // If the socket could not be created, an error message will appear
}

echo 'Socket was bind to IP';
$bind_to_ip = socket_bind($socketObject, '127.0.0.1', 7777); bind the socket to ip and the desired port
if (!$bind) {
die('Error: ' . socket_strerror(socket_last_error())); // If the binding failed, display an error message
}

echo 'Set diffrent options';
// share the work of one port for several connections
$set_option = socket_set_option($socketObject, SOL_SOCKET, SO_REUSEADDR, 1);
if (!$option) {
die('Error: ' . socket_strerror(socket_last_error()));
}

echo 'Socket Listening';
$listen = socket_listen($socketObject); // listen on the socket on the set port
if (!$listen) {
die('Error: ' . socket_strerror(socket_last_error()));
}

while (true) { // infinite loop waiting for connections
echo 'Waiting for any connections';
$connect_sucsess = socket_accept($socketObject); // pause to wait for a response
if ($connect_sucsess !== false) {
echo 'Client connection successful';
echo ‘Send data to client’;
socket_write($connect_sucsess, 'Hello World!');
} else {
echo 'Error: ' . socket_strerror(socket_last_error());
$waiting = 1000;
usleep($waiting);
}

// stop the server after $limit seconds
if ($limit && (time() - $time_to_start > $limit)) {
echo ‘Closing connection’;
socket_close($socketObject);
echo 'Server finish connection';
return;
}
}
}

error_reporting(E_ALL); display all errors and warnings that may occur when starting the server and connecting
set_time_limit(0); infinite script time, providing a permanent connection

Start the server for a while, the shutdown of which will take place in 180 seconds
SocketServer(180);

Now we need to open the PHP command line and enter the path to our file in it:

D:\project\localhost\www>php -f socket.php.

If the launch is successful, the console displays the following lines:

  1. SERVER START TO WORK;
  2. Socket was created;
  3. Socket was bind to IP;
  4. Set diffrent options;
  5. Socket Listening;
  6. Waiting for any connections.

If you disable the server, it will say Closing connection. If a WebSocket object is created on the client and a connection is created, it will say Client connection sucsessful. If the server sends data over a socket, it will say Send data to client.

However, this operation is not sufficient for the application to communicate with the server through WS. In order to ensure full operation, you need to create a client-side connection script. To do this, of course, you will have to use JavaScript. The technology is somewhat similar to AJAX.

Data transfer via sockets is carried out in the background without reloading the page. Typically, the connection is tied to some JavaScript event, for example, window.onload. Sending or receiving data is also based on an event. For example, the function of sending data is carried out by pressing any button.

In short, when the page loads, the client connects via socket to the server; when you click on the button, data is sent via the WS protocol without reloading the page.

Example: Implementing a client-side server connection function in JavaScript.

var socketObject = new WebSocket(«ws://localhost»);

socketObject.onopen = function() { // If the connection is established with the host, the browser will report this, and the text "Hello World" will be sent from the alert server
("The connection was successfully established");
alert ("Send data control frames to the server");
socket.send("Hello World");

};

socketObject.onmessage = function() { // A message will be displayed if the server receives any alert message
("Data was received from the server");

};

socketObject.onclose = function() {
alert(" Connection stopped without problems");

}
};

socket.onerror = function(error) { // A message is displayed if an alert connection
error occurs("error.message");

};

This code will work until the end of the session. After the app or page is downloaded again, the connection will be established automatically. Next, to transfer data, you need to perform an event: pressing a button and the like. This will happen all the time while the server is running.

A looped script on the server side, via PHP, is responsible for the persistent connection. This script will constantly ask the browser if there is data about the sending. If the event does not occur, the browser will respond with a "no". When you click the button, data will be sent after the server again requests the presence of frames.

You cannot use the XMLHttpRequest object for these operations. JavaScript cannot control the headers of frame and packet submissions. Only WebSocets! And only if there is a connection script located on the server.

For a low Internet connection, sending big data may be delayed. The socket.bufferedAmount property stores the number of bytes that are buffered and waiting to be sent. To increase the speed of transmission of buffered data, you should use the conditional construction:

setInterval(() => {
if (socketObject.bufferedAmount == 0) {
socketObject.send(moreData());
}
}, 100);

Here, more data will be sent every 100 milliseconds, provided that all the current bytes have already been sent.

Socket errors

Sockets are susceptible to network failures, as are many other web technologies. The server is created from a variety of functions and each of them can return a value of false in case of any failure. When a failure occurs, you can get information about the error using two functions:

  • socket_strerror($error_code). Here, $error_code is the string value returned by the socket_last_error() function. This function returns a description of the error.
  • socket_last_error($socketObject). Here, the $socket is a socket object created by the socket_create() constructor function. The function returns information about the last socket creation error. This error is represented as an integer.

Useful functions for socket manipulation in PHP

  • socket_accept(socketObject) — after the request, accepts a server-side connection for the current socket, which is inserted into the parameter;
  • socket_create_listen(port, connect_count) — accepts a connection on the specified port of the first parameter, and the second parameter indicates how much maximum can be in the queue of waiting connections;
  • socket_get_option(socketObject, level_of_protocol, option) — gets the parameters of the thread on the connection, where the second parameter specifies the protocol level on which the option from the third parameter is located. The third parameter uses one of the predefined constants that store the values of the options, which can be found in the PHP documentation. The function returns the value of the option constant, and returns false if it fails;
  • socket_last_error(socketObject) — returns the last error that occurred when a numeric connection failed;
  • socket_listen (socketObject, connect_count) — listens for connections to the server after the socket has been created and the client is attached to the server. The second parameter specifies the maximum number of expected connections that can be queued. If successful, returns true, or false on error;
  • socket_send (socketObject, sending_data, length) — sends data to the client that connected to the socket. The third parameter specifies the maximum number of bytes that will be sent to the server. Gets the number of bytes sent, or false;
  • socket_sendto (socketObject, sending_data, length, adress, port) — sending a length message to address through the port port via the socket protocol even when there is no connection;
  • socket_set_block(socketObject) — enables the mode of blocking sending data until the socket receives a signal to send data - the script on the server will be suspended. If the connection lock fails, false will be returned;
  • socket_set_option (socketObject, level_of_protocol, option) — configures socket parameters. The last parameter accepts only one of the constants provided in PHP;
  • socket_strerror(code_of_error) - Returns an error in string format. An error code is written to the parameter after the socket_last_error() function is executed;
  • socket_write (socketObject, data, length) – writes data to the socket. The optional length parameter allows you to set a limit on the size of the data to be written, which is specified in the number of bytes. Gets the number of bytes written to the socket, or false, if an error occurs.

Close a socket

When a client intentionally closes a socket, use the socket.close([code], [reason] function). This event is not done manually, but is automated by a script from the client side. Users of the application do not need to know what a socket is and should not take any interface element to close it. This function is encapsulated exclusively in script and is executed automatically depending on the conditions.

The code parameter can be:

1000 – normal closing, this value is the default;

1006 – indicates the loss of connection in the absence of a closing frame;

1001 – Disabling a server or user connected by socket;

1009 – the size of the message is larger than the aisle;

1011 – An unexpected error occurs on the server.

reason, the second parameter, is an optional string that describes why the connection was closed. You can omit this setting or use it as an explanatory note for users of your app.

Example1: Creating a socket itself

$address = ‘gmail.com’; Write to the variable hostname
$port = 80;
$socketObject = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); Create a socket object and add the necessary parameters to it, consisting of predefined constants

socket_connect($socketObject, $address, $port); Join the client in case of sending a request from his side
socket_write ($socketObject, "GET / HTTP / 1.0 \ r \ n \ r \ n "); Make an initial entry to the socket

$result = «»; Variable for storing data transmitted over the network

while($read = socket_read($socketObject, 1024)) //Retrieving the result of a socket transfer from the client
{
$result .= $read;
}
socket_close($socketObject); Close the connection

echo "Result obtained: $result\r\n"; Display the text of the message on the screen

One but significant difference between WebSocket and XMLHttpRequest

 

There is one significant difference that does not allow these two objects to be considered brothers. The fact is that these technologies carry out data transfer in the background without reloading the page. However, XMLHttpRequest only works with the HTTP protocol and does not allow you to create a persistent connection like WS.

Each time XMLHttpRequest accesses the server, a new connection is made. Therefore, this object is not suitable for creating chats and other applications in real time.

Is there an alternative way to create sockets on the server?

 

 

Of course, not only on PHP you can create socket servers. This can be done by other languages that have the necessary classes, and also use specially designed libraries to create web applications. These are Java, C#, Python, Ruby.

To use a socket server, you must create one. Of course, there are ready-made scripts. However, manual creation implies unlimited possibilities in configuring the server.

On the client side, it is also necessary to write a script for individual situations. But you can create a reference to a JavaScript file that will create the desired connection. However, events to send data will have to be created by the programmer himself. After all, you can always choose one working script to connect to the server. For the interface elements, you will have to create separate event scripts.

Final summary of web sockets

 

Sockets are a data transfer protocol that allows you to transfer text, images, and other content without having to reload the page.

Sockets are part of the OSI sibling model. They are located at the application layer along with HTTP. Data transport is subject to the TCP protocol. To use sockets, you do not need to make any settings within the network. To do this, just create a file with a PHP script and place it on the server.

A socket provides a single but constant connection of the client from the servers for the entire session, which is carried out immediately after the web page is loaded. To be able to connect the client to the server and exchange data, there must be scripts at both points that implement the ability of the client and the server to communicate.

Due to the rich set of functions and constants, data transfer over a socket can be organized in different ways. PHP has a huge number of functions for manipulating sockets. However, most often only a few of them are used.

The WebSocket object in the browser has a small number of functions. However, it is the only object that provides a WS connection. WebSocket is not an analogy to XMLHttpRequest. These objects provide data transfer in the background, but are subject to different protocols. Sockets can be used in any app or site, regardless of the type of app.

Disadvantage of sockets - not supported in older browsers (missing WebSocket object) To check for the presence of such an object, it is enough to enter its name in the browser console and press Enter. Sockets are used in online games to transmit large amounts of data in a short period of time. This ensures a high ping in games (fps is not affected, as it depends on the hardware of the computer).

Sockets can be created both to create one connection and several at the same time - often this technology is used in various chats where a large number of users participate.
Simple scripts for creating socket connections and data transfer supports can be found on the Internet. In order to complicate but give flexibility to the socket, you should know all the functions and constants reserved for sockets in PHP.

The socket only works during the session. When you close an application or a browser window, the connection is broken. A new connection is automatically created when you reload the site or app. On the hosting, a socket connection is created in the same way using a script. There you will no longer have to remove comments from the "extension = php_sockets.dll" field.