This article mainly introduces phpsocket-implemented chat room code sharing. The implementation code in this article comes from foreign friends. If you need it, refer
This article mainly introduces the chat room code sharing implemented by php socket. The implementation code in this article comes from foreign friends. If you need it, refer
/*** PatServer ** PHP socket server base class * Events that can be handled: ** onStart ** onConnect ** onConnectionRefused ** onClose ** onShutdown ** onReceiveData ** @ version 1.1 * @ author STEPHEN an Schmidt * @ Package patServer */class patServer {/*** information about the project * @ var array $ systemVars */var $ systemVars = array ("appName" => "patServer ", "appVersion" => "1.1", "author" => array ("Stephen Schmidt ",);/*** Port to listen * @ var integer $ port */var $ port = 10000; /*** domain to bind to * @ var string $ domain */var $ domain = "localhost "; /*** maximum amount of clients * @ var integer $ maxClients */var $ maxClients =-1; /*** buffer size for socket_read * @ var integer $ readBufferSize */var $ readBufferSize = 128; /*** end character for socket_read * @ var integer $ readEndCharacter */var $ readEndCharacter = "\ N";/*** maximum of backlog in queue * @ var integer $ maxQueue */var $ maxQueue = 500; /*** debug mode ** @ var boolean $ debug */var $ debug = true; /*** debug mode * @ var string $ debugMode */var $ debugMode = "text";/*** debug destination (filename or stdout) * @ var string $ debugDest */var $ debugDest = "stdout";/*** empty array, used for socket_select * @ var array $ null */var $ null = array ();/*** all file Descriptors are stored here * @ var array $ clientFD */var $ clientFD = array (); /*** needed to store client information * @ var array $ clientInfo */var $ clientInfo = array (); /*** needed to store server information * @ var array $ serverInfo */var $ serverInfo = array (); /*** amount of clients * @ var integer $ clients */var $ clients = 0; /*** create a new socket server *** @ access public * @ param string $ domain dom Ain to bind to * @ param integer $ port to listen to */function patServer ($ domain = "localhost", $ port = 10000) {$ this-> domain = $ domain; $ this-> port = $ port; $ this-> serverInfo ["domain"] = $ domain; $ this-> serverInfo ["port"] = $ port; $ this-> serverInfo ["servername"] = $ this-> systemVars ["appName"]; $ this-> serverInfo ["serverversion"] = $ this-> systemVars ["appVersion"]; set_time_limit (0);}/*** set maxi Mum amount of simultaneous connections ** @ access public * @ param int $ maxClients */function setMaxClients ($ maxClients) {$ this-> maxClients = $ maxClients ;} /*** set debug mode ** @ access public * @ param mixed $ debug [text | htmlfalse] * @ param string $ dest destination of debug message (stdout to output or filename if log shoshould be written) */function setDebugMode ($ debug, $ dest = "stdout") {if ($ debug = False) {$ this-> debug = false; return true;} $ this-> debug = true; $ this-> debugMode = $ debug; $ this-> debugDest = $ dest;}/*** start the server ** @ access public * @ param int $ maxClients */function start () {$ this-> initFD = @ socket_create (AF_INET, SOCK_STREAM, 0); if (! $ This-> initFD) die ("patServer: cocould not create socket. "); // adress may be reused socket_setopt ($ this-> initFD, SOL_SOCKET, SO_REUSEADDR, 1); // bind the socket if (! @ Socket_bind ($ this-> initFD, $ this-> domain, $ this-> port) {@ socket_close ($ this-> initFD); die ("patServer: cocould not bind socket ". $ this-> domain. "on port ". $ this-> port. "(". $ this-> getLastSocketError ($ this-> initFd ). "). ");} // listen on selected port if (! @ Socket_listen ($ this-> initFD, $ this-> maxQueue) die ("patServer: cocould not listen (". $ this-> getLastSocketError ($ this-> initFd ). "). "); $ this-> sendDebugMessage (" Listening on port ". $ this-> port. ". server started ". date ("H: I: s", time ())); // this allows the shutdown function to check whether the server is already shut down $ GLOBALS ["_ patServerStatus"] = "running"; // this ensures that the s Erver will be susudown correctly register_shutdown_function (array ($ this, "shutdown"); if (method_exists ($ this, "onStart") $ this-> onStart (); $ this-> serverInfo ["started"] = time (); $ this-> serverInfo ["status"] = "running"; while (true) {$ readFDs = array (); array_push ($ readFDs, $ this-> initFD); // fetch all clients that are awaiting connections for ($ I = 0; $ I <count ($ this-> clientFD); $ I ++) If (isset ($ this-> clientFD [$ I]) array_push ($ readFDs, $ this-> clientFD [$ I]); // block and wait for data or new connection $ ready = @ socket_select ($ readFDs, $ this-> null, $ this-> null, NULL ); if ($ ready = false) {$ this-> sendDebugMessage ("socket_select failed. "); $ this-> shutdown ();} // check for new connection if (in_array ($ this-> initFD, $ readFDs )) {$ newClient = $ this-> acceptConnection ($ this -> InitFD); // check for maximum amount of connectionsif ($ this-> maxClients> 0) {if ($ this-> clients> $ this-> maxClients) {$ this-> sendDebugMessage ("Too has connections. "); if (method_exists ($ this," onConnectionRefused ") $ this-> onConnectionRefused ($ newClient); $ this-> closeConnection ($ newClient );}} if (-- $ ready <= 0) continue;} // check all clients for incoming data for ($ I = 0; $ I <count ($ t His-> clientFD); $ I ++) {if (! Isset ($ this-> clientFD [$ I]) continue; if (in_array ($ this-> clientFD [$ I], $ readFDs )) {$ data = $ this-> readFromSocket ($ I); // empty data => connection was closedif (! $ Data) {$ this-> sendDebugMessage ("Connection closed by peer"); $ this-> closeConnection ($ I );} else {$ this-> sendDebugMessage ("Received ". trim ($ data ). "from ". $ I); if (method_exists ($ this, "onReceiveData") $ this-> onReceiveData ($ I, $ data );}}}}} /*** read from a socket ** @ access private * @ param integer $ clientId internal id of the client to read from * @ return string $ data that was read */fun Ction readFromSocket ($ clientId) {// start with empty string $ data = ""; // read data from socket while ($ buf = socket_read ($ this-> clientFD [$ clientId], $ this-> readBufferSize) {$ data. = $ buf; $ endString = substr ($ buf,-strlen ($ this-> readEndCharacter); if ($ endString = $ this-> readEndCharacter) break; if ($ buf = NULL) break;} if ($ buf = false) $ this-> sendDebugMessage ("cocould not read f Rom client ". $ clientId. "(". $ this-> getLastSocketError ($ this-> clientFD [$ clientId]). "). "); return $ data ;} /*** accept a new connection ** @ access public * @ param resource & $ socket that blocks the new connection * @ return int $ clientID internal ID of the client */function acceptConnection (& $ socket) {for ($ I = 0; $ I <= count ($ this-> clientFD); $ I ++) {if (! Isset ($ this-> clientFD [$ I]) | $ this-> clientFD [$ I] = NULL) {$ this-> clientFD [$ I] = socket_accept ($ socket); socket_setopt ($ this-> clientFD [$ I], SOL_SOCKET, SO_REUSEADDR, 1 ); $ peer_host = ""; $ peer_port = ""; socket_getpeername ($ this-> clientFD [$ I], $ peer_host, $ peer_port ); $ this-> clientInfo [$ I] = array ("host" => $ peer_host, "port" => $ peer_port, "connectOn" => time ()); $ this-> clients ++; $ this-> sendDebu GMessage ("New connection (". $ I. ") from ". $ peer_host. "on port ". $ peer_port); if (method_exists ($ this, "onConnect") $ this-> onConnect ($ I); return $ I ;}}/ *** check, whether a client is still connected ** @ access public * @ param integer $ id client id * @ return boolean $ connected true if client is connected, false otherwise */function isConnected ($ id) {if (! Isset ($ this-> clientFD [$ id]) return false; return true ;} /*** close connection to a client ** @ access public * @ param int $ clientID internal ID of the client */function closeConnection ($ id) {if (! Isset ($ this-> clientFD [$ id]) return false; if (method_exists ($ this, "onClose") $ this-> onClose ($ id ); $ this-> sendDebugMessage ("Closed connection (". $ id. ") from ". $ this-> clientInfo [$ id] ["host"]. "on port ". $ this-> clientInfo [$ id] ["port"]); @ socket_close ($ this-> clientFD [$ id]); $ this-> clientFD [$ id] = NULL; unset ($ this-> clientInfo [$ id]); $ this-> clients --;} /*** shutdown server *** @ access publi C */function shutDown () {if ($ GLOBALS ["_ patServerStatus"]! = "Running") exit; $ GLOBALS ["_ patServerStatus"] = "stopped"; if (method_exists ($ this, "onShutdown") $ this-> onShutdown (); $ maxFD = count ($ this-> clientFD); for ($ I = 0; $ I <$ maxFD; $ I ++) $ this-> closeConnection ($ I ); @ socket_close ($ this-> initFD); $ this-> sendDebugMessage ("Shutdown server. "); exit;}/*** get current amount of clients ** @ access public * @ return int $ clients amount of clients */fun Ction getClients () {return $ this-> clients ;} /*** send data to a client ** @ access public * @ param int $ clientId ID of the client * @ param string $ data to send * @ param boolean $ debugData flag to indicate whether data that is written to socket shoshould also be sent as debug message */function sendData ($ clientId, $ data, $ debugData = true) {if (! Isset ($ this-> clientFD [$ clientId]) | $ this-> clientFD [$ clientId] = NULL) return false; if ($ debugData) $ this-> sendDebugMessage ("sending :\"". $ data. "\" to: $ clientId "); if (! @ Socket_write ($ this-> clientFD [$ clientId], $ data) $ this-> sendDebugMessage ("cocould not write '". $ data. "'client ". $ clientId. "(". $ this-> getLastSocketError ($ this-> clientFD [$ clientId]). "). ");} /*** send data to all clients *** @ access public * @ param string $ data to send * @ param array $ exclude client ids to exclude */function broadcastData ($ data, $ exclude = array (), $ debugData = true) {if (! Empty ($ exclude )&&! Is_array ($ exclude) $ exclude = array ($ exclude); for ($ I = 0; $ I <count ($ this-> clientFD); $ I ++) {if (isset ($ this-> clientFD [$ I]) & $ this-> clientFD [$ I]! = NULL &&! In_array ($ I, $ exclude) {if ($ debugData) $ this-> sendDebugMessage ("sending :\"". $ data. "\" to: $ I "); if (! @ Socket_write ($ this-> clientFD [$ I], $ data) $ this-> sendDebugMessage ("cocould not write '". $ data. "'client ". $ I. "(". $ this-> getLastSocketError ($ this-> clientFD [$ I]). "). ");}}} /*** get current information about a client ** @ access public * @ param int $ clientId ID of the client * @ return array $ info information about the client */function getClientInfo ($ clientId) {if (! Isset ($ this-> clientFD [$ clientId]) | $ this-> clientFD [$ clientId] = NULL) return false; return $ this-> clientInfo [$ clientId];} /*** send a debug message ** @ access private * @ param string $ msg message to debug */function sendDebugMessage ($ msg) {if (! $ This-> debug) return false; $ msg = date ("Y-m-d H: I: s", time ()). "". $ msg; switch ($ this-> debugMode) {case "text": $ msg = $ msg. "\ n"; break; case "html": $ msg = htmlspecialchars ($ msg )."
\ N "; break;} if ($ this-> debugDest =" stdout "| empty ($ this-> debugDest) {echo $ msg; flush (); return true;} error_log ($ msg, 3, $ this-> debugDest); return true ;} /*** return string for last socket error ** @ access public * @ return string $ error last error */function getLastSocketError (& $ fd) {$ lastError = socket_last_error ($ fd); return "msg :". socket_strerror ($ lastError ). "/Code :". $ lastError;} function onReceiveData ($ ip, $ data) {$ this-> broadcastData ($ data, array (), true) ;}$ patServer = new patServer (); $ patServer-> start ();
,