tcp-server.php

Grundgerüst für einen TCP-Server in PHP

tcp-server.php
<?
	/*
	_________________________________________________________________________________________________
 
	tcp-server.php v.0.1 build 0403
	written by Heiko Barth :: 03/2008
	www.heiko-barth.de
 
	Copyright (c) 2008 Heiko Barth
 
	This script is distributed in the hope that it will be useful, but WITHOUT
	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
	FITNESS FOR A PARTICULAR PURPOSE.
 
	USING AT YOUR OWN RISK.
	_________________________________________________________________________________________________
 
	So if there's something you don't like, don't sit on the sidelines. Get involved and reform it.
	Evolution works better than revolution, after all!
 
	*/
 
	//	<Configuration>	//
 
		$interface = 0;		// 0 = all interfaces, otherwise enter interface ip
		$port = 5555;		// listen port
		$connections = 50;	// max concurrent connetions
 
	//	</Configuration>	//
 
	set_time_limit(0);
	ob_implicit_flush();
 
	// check if socket extension is available
	if (!function_exists('socket_create')) {
		if(!(@dl("php_sockets.so") || @dl("php_sockets.dll"))) {
			die("Error: Socket extension not available.\n");
		}
	}	
 
	//	<Creating & Binding socket>	//
		$sock = @socket_create(AF_INET, SOCK_STREAM, getprotobyname("TCP")) or
			die("Error creating socket.\n");
		@socket_bind($sock, $interface, $port) or
			die("Error binding socket. Port $port is already in use!?\n");
		@socket_listen($sock, $connections) or 
			die("Error while setting listen mode on socket.\n");
	//	</Creating & Binding socket>	//	
 
	$clients = array();
 
	// monitor socks
	do {
		$updatesocks = array();
		$updatesocks[] = $sock;
 
		foreach($clients as $clientsock) {
			$updatesocks[] = $clientsock;
		}
 
		// check wait for incoming connections
		$sockschanged = socket_select($updatesocks, $writesocks, $errorsocks, 1);
 
		if ($sockschanged > 0) {
			foreach($updatesocks as $csock) {
				if ($csock == $sock) {
					// accept connection
					if (count($clients) < $connections) {
						$newsock = socket_accept($sock);
						if ($newsock) {
							$clients[] = $newsock;
							client_connected($newsock);
						}
					}
				}
				else {
					// call function to handle client data
					$sockdata = @socket_read($csock, 512);
					if (($sockdata !== false) && ($sockdata != "")) { // !== handles case character "0" was send
						if ($sockdata != "") {
							handle_client($sockdata);
						}
						else {
							// closed socket!? --> recognized by tests with the apache benchmark utility while creating timeouts
							remove_client();
						}
					}
					else {
						// on error: close socket and delete client from array
						// echo socket_last_error($csock);
						remove_client();
					}
				}
			}
		}
		// shows connections at console title; win32 only
		#$cmd = "title Connections: " . count($clients);
		#`$cmd`;
	} while (true);
 
	// use this functin to handle client input
	// $data contains the data send by the client
	// use "socket_write($csock, $YOURDATA, strlen($YOURDATA));" to send data to the client
 
	function client_connected($sock) {
		socket_getpeername($sock, $ip);
		echo $ip . " connected\n";
	}
 
	function handle_client($data) {
		global $csock;
		socket_getpeername($csock, $ip);
		echo  "[$ip] " . trim($data) . "\n";
		if (@socket_write($csock, "ok\n") === false) {
			remove_client();
		}
	}
 
	$buffer = array();
 
	function remove_client() {
		echo "Client disconnected\n";
		global $csock;
		global $clients;
		$arr = array_keys($clients, $csock);
		unset($clients[$arr[0]]);
		@socket_shutdown($csock);
		@socket_close($csock);
	}