How to create a socket server in PHP

Published on Mar 2, 2009 by Jamie Munro

Ever want to build a chat application or perhaps even a game? If so, a socket server will help you get started. Once you understand the underlying functionality of creating the server, enhancing it is just as easy.


The way a socket server works is, it will be running continously and waiting for a client to connect to it. When a client connects, our server will add it to our list of clients and begin waiting for messages from that client.


Without further adieu, here is the full source code:



// Set time limit to indefinite execution
set_time_limit (0);

// Set the ip and port we will listen on
$address = 'localhost';
$port = 10000;
$max_clients = 10;

// Array that will hold client information
$client = Array();

// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port) or die('Could not bind to address');
// Start listening for connections
socket_listen($sock);

echo "Waiting for connections...\r\n";

// Loop continuously
while (true) {
	// Setup clients listen socket for reading
	$read[0] = $sock;
	for ($i = 0; $i < $max_clients; $i++) {
		if (isset($client[$i]['sock']))
			$read[$i + 1] = $client[$i]['sock'];
	}
	// Set up a blocking call to socket_select()
	if (socket_select($read, $write = NULL, $except = NULL, $tv_sec = 5) < 1)
		continue;
	/* if a new connection is being made add it to the client array */
	if (in_array($sock, $read)) {
		for ($i = 0; $i < $max_clients; $i++) {
			if (empty($client[$i]['sock'])) {
				$client[$i]['sock'] = socket_accept($sock);
				echo "New client connected $i\r\n";
				break;
			}
			elseif ($i == $max_clients - 1)
				echo "Too many clients...\r\n";
		}
	} // end if in_array
	
	// If a client is trying to write - handle it now
	for ($i = 0; $i < $max_clients; $i++) { // for each client
		if (isset($client[$i]['sock'])) {
			if (in_array($client[$i]['sock'], $read)) {
				$input = socket_read($client[$i]['sock'], 1024);
				if ($input == null) {
					echo "Client disconnecting $i\r\n";
					// Zero length string meaning disconnected
					unset($client[$i]);
				} else {
					echo "New input received $i\r\n";
					// send it to the other clients
					for ($j = 0; $j < $max_clients; $j++) {
						if (isset($client[$j]['sock']) && $j != $i) {
							echo "Writing '$input' to client $j\r\n";
							socket_write($client[$j]['sock'], $input, strlen($input));
						}
					}
					if ($input == 'exit') {
						// requested disconnect
						socket_close($client[$i]['sock']);
					}
				}
			} else {
				echo "Client disconnected $i\r\n";
				// Close the socket
				socket_close($client[$i]['sock']);
				unset($client[$i]);
			}
		}
	}
} // end while
// Close the master sockets
socket_close($sock);

Obviously, at first glance it might seem that a lot is going on, but let's begin by breaking it down into a few smaller sections. The first section, is the creation of the server. Lines: 2 through 20.


This portion of code sets a few variables, our address, port, max clients, and clients array. Next up it creates the socket and binds it to the address and port we specified. Finally it begins listening for messages.


The next thing we do is perform an endless loop (yeah one that we actually made purposely!). Lines: 22 through 32. In the first part of the next code we are setting up our $read array. This array contains all of our client sockets and our main server socket. This variable is used later in our select statement telling PHP to listen for any messages from these clients.


The last parameter of socket_select() tells our server to wait a maximum of 5 seconds before returning something. If what it's returned is less than 1, we received no data, so we just go back to the top of our loop and keep waiting.


The next part of our script, adds a new client to our array. Lines: 33 through 44.


Once we have a new client we place them at the end of the list. We also do a check to ensure we do not have more clients than we want our server to handle.


The next chunk of code is a rather large chunk and it's the meat of our server. The following code handles when a client sends a message to the server. This message can vary from a disconnect message, our an actual disconnect, or any other message that our server needs to handle. Lines: 46 through the rest of the script.


The code loops through each client and checks if the message was received by them. If it was, we get what the input was. Based on the input we check if it's a disconnect message, if so we remove them from our array, otherwise, if it's a regular message our server loops through all of the clients again and writes the message to them one at a time, skipping the sender.


That's it, enjoy creating your very own chat server!

Tags: php | chat server | socket server | Theory | PHP

Related Posts

blog comments powered by Disqus