An Introduction to Sockets in PHP

Working with low-level sockets can be a painful task in PHP. Fortunately, PHP offers a nice library of socket handling functions to make your life easier. If you do a lot of network programming in PHP, you will want to check out this three-part series, which starts with the basics and takes you through more advanced approaches. This article is the first one in the series.

Introduction

In the vast and exciting terrain of network programming in PHP, working with low-level sockets can be a cumbersome task. Most of the time, when you are developing a Web application, you do not go very deep into the manipulation of the lower-level features of a network operating system.

If you’ve been using sockets in PHP, you probably know what I’m talking about. Writing, reading and controlling socket streams can be achieved well enough with the help of a comprehensive set of native PHP functions, such as the popular “fsockopen()”, and “fputs()/fgets()” functions, and eventually the use of an iteration routine. This sounds relatively simple, and certainly will suit most of your socket programming needs. However, there are times when the requirements of a specific PHP project demand using low-level sockets, in order to implement, for example, a testing TCP-based server, and the corresponding client applications that will interact with it.

In order to tackle this kind of situations (and many more, by the way), luckily PHP offers a nice library of socket handling functions, which can be used to create server and client applications, manipulate data streams, and perform many more tasks related to low-level network programming. With reference to using sockets in PHP, in this three-part series, I’ll try to cover their most crucial aspects. I’ll start with the basics, such as creating, opening and closing a socket. Then I will proceed to using advanced approaches, such as implementing socket servers. Of course, I’ll accompany this material with numerous hands-on examples.

At the end of this series, you should be equipped with a good grounding in how to use and manipulate low-level sockets in PHP, in order to expand your existing background of network programming.

Now that you know the topics that will be discussed over this series, it’s time to leap forward and begin learning the fundamentals of low-level sockets in PHP. It’s going to be instructive, so let’s get started.

{mospagebreak title=The basics of low-level sockets: developing an illustrative example}

In order to introduce the core concepts of socket programming in PHP in a friendly way, I’m going to set up a basic example, which hopefully will help to illustrate the usage of the most important socket-related PHP functions. First I’ll show you how to develop a simple TCP server with sockets, and then I’ll explain the meaning of each function used in the sample script.

Having said that, here’s a procedural script that builds a basic TCP server. Take a look at the code listed below:

// define TCP port & local host
$port=1234;
$host=’127.0.0.1′;
set_time_limit(0);
// create low level socket
if(!$socket=socket_create(AF_INET,SOCK_STREAM,0)){
    trigger_error(‘Error creating new socket’,E_USER_ERROR);
}
// tie up socket to TCP port
if(!socket_bind($socket,$host,$port)){
    trigger_error(‘Error binding socket to TCP
port’,E_USER_ERROR);
}
// begin listening connections
if(!socket_listen($socket)){
    trigger_error(‘Error listening socket
connections’,E_USER_ERROR);
}
// create communication socket
if(!$comSocket=socket_accept($socket)){
    trigger_error(‘Error creating communication
socket’,E_USER_ERROR);
}
// read socket input
$socketInput=socket_read($comSocket,1024);
// convert to uppercase socket input
$socketOutput=strtoupper(trim($socketInput)).”n”;
// write data back to socket server
if(!socket_write($comSocket,$socketOutput,strlen($socketOutput))){
    trigger_error(‘Error writing socket output’,E_USER_ERROR);
}
// close sockets
socket_close($comSocket);
socket_close($socket);

As you can see, the procedural script listed above demonstrates how to create a simple TCP server, where its only functionality rests in taking up a string sent by a client, then converting it to its uppercase version and finally returning it to the mentioned client. Does that sound a little bit confusing? Don’t worry, it really isn’t.

First, the script defines the host and port number where the TCP server will be running. In this specific case the server will be created to work as “localhost,” that is its IP address will be 127.0.0.1 and it will run on the TCP port “1234.”

After defining the corresponding connection parameters, the first connection socket is created by the “create_socket()” PHP built-in function, which obviously creates and returns a socket reference. Also, the first argument of this function–that is the domain parameter–specifies the protocol family to be used by the socket, in this case AF_INET, which means that it will use the IPv4 Internet-based protocols.

Additionally, the second argument indicates the type of socket to be used. In this example, I specified a value of “SOCK_STREAM,” meaning that the socket will support the use of the TCP protocol. Finally, the last function parameter determines the protocol used by the socket. In this case I decided to use the reliable TCP protocol.

Of course, all the above description can be assumed in the following statement:

// create low level socket
if(!$socket=socket_create(AF_INET,SOCK_STREAM,0)){
    trigger_error(‘Error creating new socket’,E_USER_ERROR);
}

Right, after creating the general connection socket, the script needs to bind it to the host and port defined before. To perform this operation, the “socket_bind()” function is conveniently used, as listed below:

// tie up socket to TCP port
if(!socket_bind($socket,$host,$port)){
    trigger_error(‘Error binding socket to TCP
port’,E_USER_ERROR);
}

At this point, I created a general connection socket, which is tied to the 127.0.0.1 IP address, and will be expecting incoming connections on the TCP port 1234. Now, how do I make the socket listen to client connections? Right, you guessed it,  the “socket_listen()” function does precisely that:

// begin listening connections
if(!socket_listen($socket)){
    trigger_error(‘Error listening socket
connections’,E_USER_ERROR);
}

Now that the general connection socket has been created and it’s expecting client connections, there are a few additional things to be done yet. The first one consists of creating another communication socket, which will handle all the operations for reading and writing data. This is achieved by the “socket_read()” and “socket_write()” PHP functions respectively, and the entire reading-writing sequence is illustrated below:

// read socket input
$socketInput=socket_read($comSocket,1024);
// convert to uppercase socket input
$socketOutput=strtoupper(trim($socketInput)).”n”;
// write data back to socket server
if(!socket_write($comSocket,$socketOutput,strlen($socketOutput)))
{
    trigger_error(‘Error writing socket output’,E_USER_ERROR);
}

As you can see, the above code block first reads the data sent by the client, then converts the data to uppercase and writes the string back to the client. At the end of this process, both sockets, the general and the communication one, are closed by the “socket_close()” PHP function, as shown below:

// close sockets
socket_close($comSocket);
socket_close($socket);

Wasn’t that simple and fun? With a few PHP functions, I created an admittedly basic TCP server that returns the uppercase version of any string sent out by the client.

Also, before I finish writing this section, I’d like you to notice that the script uses the “set_time_limit()” function, in order to get rid of any timeouts imposed by the PHP parser. This makes a lot of sense, since the script doesn’t have a clue about when an eventual client is going to inject data into the socket, so eliminating timeouts is a good approach to keep the script working properly.

Now, the sample TCP server is up and running, listening to incoming client connections. Therefore, a client application should be created, in order to determine whether the sockets just created work as expected. That’s exactly what I’ll do in the next section, thus click on the link below to find out how this client is created.

{mospagebreak title=Reading and writing socket data: creating a simple web-based client application}

Creating a client application to test the sample TCP server is a straightforward task. Essentially, I’ll build a web-based script that will connect to the aforementioned server and send a string of data via an online form. In accordance with the logic implemented on the server, this string should be returned to the client in uppercase, and finally displayed on the browser.

Here’s the snippet of code that creates a simple web-based client, handy for testing the TCP server in question:

<?php
// check if form was submitted
if($_POST['send']){
    // open client connection to TCP server
    if(!$fp=fsockopen(‘127.0.0.1′,1234,$errstr,$errno,30)){
        trigger_error(‘Error opening socket’,E_USER_ERROR);
    }
    $message=$_POST['message'];
    // write message to socket server
    fputs($fp,$message);
    // get server response
    $ret=fgets($fp,1024);
    // close socket connection
    fclose($fp);
    echo ‘<h1>You entered the following message in
lowercase :’.$ret.'</h1>';
    exit();
}
?>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html>
<head>
<title>TESTING TCP SOCKET SERVER</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=iso-
8859-1″ />
</head>
<body>
<h1>Enter your message here</h1>
<form action=”<?php echo $_SERVER['PHP_SELF']?>” method=”post”>
<input type=”text” name=”message” size=”30″ /><br />
<input type=”submit” name=”send” value=”Send Value” />
</form>
</body>
</html>

As you can appreciate, the above script uses the PHP “fsockopen()” function, in order to connect to the recently created TCP server and inject into the socket the string entered in the online form. After receiving the uppercase string, the script displays this data and finishes its execution.

To understand the functionality of the sample TCP server, please take a look at the following screen shots, which illustrate both the client petition and the server response respectively:

As depicted above, the images show the TCP server in action. First, the client submits a message via the online form, and secondly the server turns the input to an uppercase string, which is finally echoed to the browser.

In addition, before I explain more concepts related to socket programming in PHP, I want to clarify one important point regarding the example: you should run the script that creates the TCP server from the PHP command line, instead of using your browser, in order to prevent the system from hanging. This can be done easily by using the CLI.exe file that comes with your PHP distribution and typing the following commands in your system shell:

q- tcpserver.php

The following screen shot shows how to start the TCP server using the PHP command line on a Windows system:

Assuming that the TCP server has been coded in a file called “tcpserver.php,” the above command should run this file and start the server (the preceding q flag tells the PHP interpreter to suppress the “Content-type” HTTP header). After making sure the server is up and running, you can point your browser to the PHP file that builds the corresponding client, and run the pertinent file.

Right, now you see how the sockets I created in the previous section do their job, reading and writing the corresponding data. Since the example TCP server has been created with a few lines of procedural code, it’d be very convenient to encapsulate the whole source code within a compact function (and incidentally within a class), so the server can be reused as many times as needed.

If you’re interested in learning how this can be achieved, please read the next few lines of the article.

{mospagebreak title=Reusing the TCP server: defining the “createSocketServer()” function and “SocketServer” class}

As I said in the previous section, it’d be really handy to encapsulate the full code for creating the sample TCP server into one single function. The function would perform basically the same task, but have the advantage of making the code much more compact and reusable. Bearing in mind this concept, here’s the definition for the corresponding “createSocketServer()” function:

function createSocketServer($host=’127.0.0.1′,$port=1234){
    if(!preg_match(“/^d{1,3}.d{1,3}.d{1,3}.d{1,3}
$/”,$host)){
        trigger_error(‘Invalid IP address format.’,E_USER_ERROR);
    }
    if(!is_int($port)||$port<1||$port>65535){
        trigger_error(‘Invalid TCP port number.’,E_USER_ERROR);
    }
    set_time_limit(0);
    // create low level socket
    if(!$socket=socket_create(AF_INET,SOCK_STREAM,0)){
        trigger_error(‘Error creating new socket.’,E_USER_ERROR);
    }
    // bind socket to TCP port
    if(!socket_bind($socket,$host,$port)){
        trigger_error(‘Error binding socket to TCP
port.’,E_USER_ERROR);
    }
     // begin listening connections
    if(!socket_listen($socket)){
        trigger_error(‘Error listening socket
connections.’,E_USER_ERROR);
    }
    // create communication socket
    if(!$comSocket=socket_accept($socket)){
        trigger_error(‘Error creating communication
socket.’,E_USER_ERROR);
    }
    // read socket input
    $socketInput=socket_read($comSocket,1024);
    // convert to uppercase socket input 
    $socketOutput=strtoupper(trim($socketInput)).”n”;     
    // write data back to socket server
    if(!socket_write($comSocket,$socketOutput,strlen
($socketOutput))){
        trigger_error(‘Error writing socket output’,E_USER_ERROR);
    }
    // close sockets
    socket_close($comSocket);
    socket_close($socket);
}

As shown above, I hid all the complexities of creating the socket server, as well as reading, processing and returning client data in just one function, which I called “createSocketServer.” This function does basically the same thing as the previous script, and introduces some additional checking code, in order to make sure that the two incoming arguments, that is the IP address and the TCP port respectively, have a valid format.

Now, creating the previous TCP server could be reduced to a process as simple as this:

// call ‘createSocketServer()’ function
createSocketServer();

I told you it was simple! Again, remember first to save this function to a file and next run it from the PHP command line (also, it’s possible to connect to the TCP server by using a Telnet client), in order to get things working appropriately.

Now that you know how the “createSocketServer()” function works, please have a look at the following PHP snippet, which encapsulates all the source code required for building the prior TCP server in one class:

class SocketServer{
    var $host;
    var $port;
    function  SocketServer($host=’127.0.0.1′,$port=1234){
        if(!preg_match(“/^d{1,3}.d{1,3}.d{1,3}.d{1,3}
$/”,$host)){
            trigger_error(‘Invalid IP address
format.’,E_USER_ERROR);
        }
        if(!is_int($port)||$port<1||$port>65535){
            trigger_error(‘Invalid TCP port
number.’,E_USER_ERROR);
        }
        $this->host=$host;
        $this->port=$port;
        $this->connect();
    }
    function connect(){
        set_time_limit(0);
        // create low level socket
        if(!$socket=socket_create(AF_INET,SOCK_STREAM,0)){
            trigger_error(‘Error creating new
socket.’,E_USER_ERROR);
        }
        // bind socket to TCP port
        if(!socket_bind($socket,$this->host,$this->port)){
            trigger_error(‘Error binding socket to TCP
port.’,E_USER_ERROR);
        }
        // begin listening connections
        if(!socket_listen($socket)){
            trigger_error(‘Error listening socket
connections.’,E_USER_ERROR);
        }
        // create communication socket
        if(!$comSocket=socket_accept($socket)){
            trigger_error(‘Error creating communication
socket.’,E_USER_ERROR);
        }
        // read socket input
        $socketInput=socket_read($comSocket,1024);
        // convert to uppercase socket input 
        $socketOutput=strtoupper(trim($socketInput)).”n”;
        // write data back to socket server
        if(!socket_write($comSocket,$socketOutput,strlen
($socketOutput))){
            trigger_error(‘Error writing socket
output’,E_USER_ERROR);
        }
        // close sockets
        socket_close($comSocket);
        socket_close($socket);
    }
}

In this case, I turned the “createSocketServer()” function into a fully working PHP class, thus if you feel inclined to work with object-oriented applications, this class could be quite appealing to you.

After building the “SocketServer” class, creating and using the prior TCP server can be reduced to the following two-liner:

// instantiate new ‘SocketServer’ object
$socket=&new SocketServer(); 

That’s it. In this article I’ve shown you different flavors of the same TCP server, according to your programming needs, so I guess there’s enough code to provide you with long hours of fun!

To wrap up

Over this first part of the series, you hopefully learned the basics of how to create sockets in PHP, as well as read, process and write socket data through an instructive example, aimed at building a simple TCP server. However, there’s still a huge area to be explored. Bearing this in mind, in the next article, I’ll show you how to use low-level sockets, in order to build a “smarter” and more complex TCP server. You won’t want to miss it!

[gp-comments width="770" linklove="off" ]

antalya escort bayan antalya escort bayan Antalya escort diyarbakir escort