7 $leaving = array("/leave", "/logout", "/bye", "/quit");
8 $shutdown = array("/shutdown", "/halt");
9 $masters = array("127.0.0.1");
11 // create a streaming socket, of type TCP/IP
12 $main_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
14 // set the option to reuse the port
15 socket_set_option($main_sock, SOL_SOCKET, SO_REUSEADDR, 1);
17 // "bind" the socket to the address to "localhost", on port $port
18 // so this means that all connections on this port are now our resposibility to send/recv data, disconnect, etc..
19 socket_bind($main_sock, "{$host}", $port);
21 // start listen for connections
22 socket_listen($main_sock);
24 // create a list of all the clients that will be connected to us..
25 // add the listening socket to this list
26 $clients = array($main_sock);
28 print "[".date("m/d/Y:H:i:s", time())."]:Server listens on {$host}:{$port}\n\n";
30 while (count($clients) > 0) {
31 // create a copy, so $clients doesn't get modified by socket_select()
34 // get a list of all the clients that have data to be read from
35 // if there are no clients with data, go to next iteration
36 $left = @socket_select($read, $write = null, $except = null, 0);
41 // check if there is a client trying to connect
42 if (in_array($main_sock, $read)) {
43 // accept the client, and add him to the $clients array
44 $new_sock = socket_accept($main_sock);
45 $clients[] = $new_sock;
47 // send the client a welcome message
48 socket_write($new_sock, "no noobs, but ill make an exception :)\n".
49 "There are ".(count($clients) - 1)." client(s) connected to the server\n");
51 socket_getpeername($new_sock, $ip);
52 print "[".date("m/d/Y:H:i:s", time())."]:New client connected: {$ip}\n";
55 if (count($clients) > 2) {
56 foreach ($clients as $send_sock) {
57 if ($send_sock != $main_sock && $send_sock != $new_sock) {
58 socket_write($send_sock, "Server: Chatter has joined from {$ip}. There are now ".(count($clients) - 1)." clients.\n");
63 // remove the listening socket from the clients-with-data array
64 $key = array_search($main_sock, $read);
68 // loop through all the clients that have data to read from
69 foreach ($read as $read_sock) {
71 socket_getpeername($read_sock, $ip);
73 // read until newline or 1024 bytes
74 // socket_read while show errors when the client is disconnected, so silence the error messages
75 $data = @socket_read($read_sock, 1024, PHP_NORMAL_READ);
77 // check if the client is disconnected
78 if (($data === false) || (in_array(strtolower(trim($data)), $leaving))) {
80 // remove client for $clients array
81 $key = array_search($read_sock, $clients);
82 unset($clients[$key]);
83 print "[".date("m/d/Y:H:i:s", time())."]:Client from {$ip} disconnected. Left: ".(count($clients) - 1)."\n";
86 if (count($clients) > 1) {
87 foreach ($clients as $send_sock) {
88 if ($send_sock != $main_sock) {
89 socket_write($send_sock, "Server: Chatter from {$ip} has logged out. ".(count($clients) - 1)." left.\n");
94 // continue to the next client to read from, if any
95 socket_write($read_sock, "Server: Good bye.\n");
96 socket_shutdown($read_sock, 2);
97 socket_close($read_sock);
99 } elseif (in_array(trim($data), $shutdown)) {
100 // Is he allowed to shutdown?
101 if (!in_array($ip, $masters)) {
102 print "[".date("m/d/Y:H:i:s", time())."]:Client $ip has tried to shutdown the server!\n";
103 socket_write($read_sock, "Server: You are not allowed to shutdown the server!\n");
108 // Close all connections a leave here
109 foreach ($clients as $client) {
110 // Send message to client
111 if ($client !== $main_sock && $client != $read_sock) {
112 socket_write($client, "Server: Shutting down! Thank you for joining us.\n");
116 socket_shutdown($client, 2);
117 socket_close($client);
126 // trim off the trailing/beginning white spaces
129 // Test for HTML codes
130 $tags = strip_tags($data);
132 // check if there is any data after trimming off the spaces
133 if (!empty($data) && $tags == $data && count($clients) > 2) {
134 // send this to all the clients in the $clients array (except the first one, which is a listening socket)
135 foreach ($clients as $send_sock) {
137 // if its the listening sock or the client that we got the message from, go to the next one in the list
138 if ($send_sock == $main_sock || $send_sock == $read_sock)
141 // write the message to the client -- add a newline character to the end of the message
142 socket_write($send_sock, "{$ip}:{$data}\n");
144 } // end of broadcast foreach
146 // Send confirmation to "chatter"
147 socket_write($read_sock, "\nServer: Message accepted.\n");
148 } elseif ($tags != $data) {
149 // HTML codes are not allowed
150 print "[".date("m/d/Y:H:i:s", time())."]:Client $ip has entered HTML code!\n";
151 socket_write($read_sock, "Server: HTML is forbidden!\n");
152 } elseif ((count($clients) == 2) && ($read_sock != $main_sock)) {
153 // No one else will hear the "chatter"
154 print "[".date("m/d/Y:H:i:s", time())."]:Client $ip speaks with himself.\n";
155 socket_write($read_sock, "Server: No one will hear you!\n");
157 } // end of reading foreach
160 // close the listening socket
161 socket_close($main_sock);