phpsocket实现的聊天室代码分享
代码 实现 分享 聊天室 phpsocket
2023-06-13 09:15:42 时间
/** *patServer *PHPsocketserverbaseclass *Eventsthatcanbehandled: **onStart **onConnect **onConnectionRefused **onClose **onShutdown **onReceiveData * *@version1.1 *@authorStephanSchmidt<schst@php-tools.de> *@packagepatServer */ classpatServer{ /** *informationabouttheproject *@vararray$systemVars */ var$systemVars=array( "appName"=>"patServer", "appVersion"=>"1.1", "author"=>array("StephanSchmidt<schst@php-tools.de>",) ); /** *porttolisten *@varinteger$port */ var$port=10000; /** *domaintobindto *@varstring$domain */ var$domain="localhost"; /** *maximumamountofclients *@varinteger$maxClients */ var$maxClients=-1; /** *buffersizeforsocket_read *@varinteger$readBufferSize */ var$readBufferSize=128; /** *endcharacterforsocket_read *@varinteger$readEndCharacter */ var$readEndCharacter="\n"; /** *maximumofbackloginqueue *@varinteger$maxQueue */ var$maxQueue=500; /** *debugmode *@varboolean$debug */ var$debug=true; /** *debugmode *@varstring$debugMode */ var$debugMode="text"; /** *debugdestination(filenameorstdout) *@varstring$debugDest */ var$debugDest="stdout"; /** *emptyarray,usedforsocket_select *@vararray$null */ var$null=array(); /** *allfiledescriptorsarestoredhere *@vararray$clientFD */ var$clientFD=array(); /** *neededtostoreclientinformation *@vararray$clientInfo */ var$clientInfo=array(); /** *neededtostoreserverinformation *@vararray$serverInfo */ var$serverInfo=array(); /** *amountofclients *@varinteger$clients */ var$clients=0; /** *createanewsocketserver * *@accesspublic *@paramstring$domaindomaintobindto *@paraminteger$portporttolistento */ functionpatServer($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); } /** *setmaximumamountofsimultaneousconnections * *@accesspublic *@paramint$maxClients */ functionsetMaxClients($maxClients) { $this->maxClients=$maxClients; } /** *setdebugmode * *@accesspublic *@parammixed$debug[text|htmlfalse] *@paramstring$destdestinationofdebugmessage(stdouttooutputorfilenameiflogshouldbewritten) */ functionsetDebugMode($debug,$dest="stdout") { if($debug===false) { $this->debug=false; returntrue; } $this->debug=true; $this->debugMode=$debug; $this->debugDest=$dest; } /** *starttheserver * *@accesspublic *@paramint$maxClients */ functionstart() { $this->initFD=@socket_create(AF_INET,SOCK_STREAM,0); if(!$this->initFD) die("patServer:Couldnotcreatesocket."); //adressmaybereused socket_setopt($this->initFD,SOL_SOCKET,SO_REUSEADDR,1); //bindthesocket if(!@socket_bind($this->initFD,$this->domain,$this->port)) { @socket_close($this->initFD); die("patServer:Couldnotbindsocketto".$this->domain."onport".$this->port."(".$this->getLastSocketError($this->initFd).")."); } //listenonselectedport if(!@socket_listen($this->initFD,$this->maxQueue)) die("patServer:Couldnotlisten(".$this->getLastSocketError($this->initFd).")."); $this->sendDebugMessage("Listeningonport".$this->port.".Serverstartedat".date("H:i:s",time())); //thisallowstheshutdownfunctiontocheckwhethertheserverisalreadyshutdown $GLOBALS["_patServerStatus"]="running"; //thisensuresthattheserverwillbesutdowncorrectly 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); //fetchallclientsthatareawaitingconnections for($i=0;$i<count($this->clientFD);$i++) if(isset($this->clientFD[$i])) array_push($readFDs,$this->clientFD[$i]); //blockandwaitfordataornewconnection $ready=@socket_select($readFDs,$this->null,$this->null,NULL); if($ready===false) { $this->sendDebugMessage("socket_selectfailed."); $this->shutdown(); } //checkfornewconnection if(in_array($this->initFD,$readFDs)) { $newClient=$this->acceptConnection($this->initFD); //checkformaximumamountofconnections if($this->maxClients>0) { if($this->clients>$this->maxClients) { $this->sendDebugMessage("Toomanyconnections."); if(method_exists($this,"onConnectionRefused")) $this->onConnectionRefused($newClient); $this->closeConnection($newClient); } } if(--$ready<=0) continue; } //checkallclientsforincomingdata for($i=0;$i<count($this->clientFD);$i++) { if(!isset($this->clientFD[$i])) continue; if(in_array($this->clientFD[$i],$readFDs)) { $data=$this->readFromSocket($i); //emptydata=>connectionwasclosed if(!$data) { $this->sendDebugMessage("Connectionclosedbypeer"); $this->closeConnection($i); } else { $this->sendDebugMessage("Received".trim($data)."from".$i); if(method_exists($this,"onReceiveData")) $this->onReceiveData($i,$data); } } } } } /** *readfromasocket * *@accessprivate *@paraminteger$clientIdinternalidoftheclienttoreadfrom *@returnstring$datadatathatwasread */ functionreadFromSocket($clientId) { //startwithemptystring $data=""; //readdatafromsocket 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("Couldnotreadfromclient".$clientId."(".$this->getLastSocketError($this->clientFD[$clientId]).")."); return$data; } /** *acceptanewconnection * *@accesspublic *@paramresource&$socketsocketthatreceivedthenewconnection *@returnint$clientIDinternalIDoftheclient */ functionacceptConnection(&$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->sendDebugMessage("Newconnection(".$i.")from".$peer_host."onport".$peer_port); if(method_exists($this,"onConnect")) $this->onConnect($i); return$i; } } } /** *check,whetheraclientisstillconnected * *@accesspublic *@paraminteger$idclientid *@returnboolean$connectedtrueifclientisconnected,falseotherwise */ functionisConnected($id) { if(!isset($this->clientFD[$id])) returnfalse; returntrue; } /** *closeconnectiontoaclient * *@accesspublic *@paramint$clientIDinternalIDoftheclient */ functioncloseConnection($id) { if(!isset($this->clientFD[$id])) returnfalse; if(method_exists($this,"onClose")) $this->onClose($id); $this->sendDebugMessage("Closedconnection(".$id.")from".$this->clientInfo[$id]["host"]."onport".$this->clientInfo[$id]["port"]); @socket_close($this->clientFD[$id]); $this->clientFD[$id]=NULL; unset($this->clientInfo[$id]); $this->clients--; } /** *shutdownserver * *@accesspublic */ functionshutDown() { 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("Shutdownserver."); exit; } /** *getcurrentamountofclients * *@accesspublic *@returnint$clientsamountofclients */ functiongetClients() { return$this->clients; } /** *senddatatoaclient * *@accesspublic *@paramint$clientIdIDoftheclient *@paramstring$datadatatosend *@paramboolean$debugDataflagtoindicatewhetherdatathatiswrittentosocketshouldalsobesentasdebugmessage */ functionsendData($clientId,$data,$debugData=true) { if(!isset($this->clientFD[$clientId])||$this->clientFD[$clientId]==NULL) returnfalse; if($debugData) $this->sendDebugMessage("sending:\"".$data."\"to:$clientId"); if(!@socket_write($this->clientFD[$clientId],$data)) $this->sendDebugMessage("Couldnotwrite"".$data.""client".$clientId."(".$this->getLastSocketError($this->clientFD[$clientId]).")."); } /** *senddatatoallclients * *@accesspublic *@paramstring$datadatatosend *@paramarray$excludeclientidstoexclude */ functionbroadcastData($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("Couldnotwrite"".$data.""client".$i."(".$this->getLastSocketError($this->clientFD[$i]).")."); } } } /** *getcurrentinformationaboutaclient * *@accesspublic *@paramint$clientIdIDoftheclient *@returnarray$infoinformationabouttheclient */ functiongetClientInfo($clientId) { if(!isset($this->clientFD[$clientId])||$this->clientFD[$clientId]==NULL) returnfalse; return$this->clientInfo[$clientId]; } /** *sendadebugmessage * *@accessprivate *@paramstring$msgmessagetodebug */ functionsendDebugMessage($msg) { if(!$this->debug) returnfalse; $msg=date("Y-m-dH:i:s",time())."".$msg; switch($this->debugMode) { case"text": $msg=$msg."\n"; break; case"html": $msg=htmlspecialchars($msg)."<br/>\n"; break; } if($this->debugDest=="stdout"||empty($this->debugDest)) { echo$msg; flush(); returntrue; } error_log($msg,3,$this->debugDest); returntrue; } /** *returnstringforlastsocketerror * *@accesspublic *@returnstring$errorlasterror */ functiongetLastSocketError(&$fd) { $lastError=socket_last_error($fd); return"msg:".socket_strerror($lastError)."/Code:".$lastError; } functiononReceiveData($ip,$data){ $this->broadcastData($data,array(),true); } } $patServer=newpatServer(); $patServer->start();
相关文章
- C语言实现读取文件的简单代码「建议收藏」
- [Java][Java加密与解密]《对称加密简单概念与代码实现》
- VB实现的16位和32位md5加密代码分享
- C#实现公式计算验证码的案例分享实现代码
- 清华&腾讯最新算法Next3D!高质量3D 感知合成,支持3D风格画!论文/代码速递2022.11.24!
- C/C++ 实现文件自校验代码
- js匿名调用实现代码
- javascripthashtable实现代码
- phpXPath对XML文件查找及修改实现代码
- C#实现大数字运算的实例代码
- Javascript脚本实现静态网页加密实例代码
- JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
- Hibernate一对多关联双向关联代码实现分享
- c#实现51单片机频率计的代码分享(数字频率计设计)
- 使用mutex实现应用程序单实例运行代码分享
- java实现优酷视频地址解析示例代码分享
- python实现异步回调机制代码分享
- 用sql实现18位身份证校验代码分享身份证校验位计算
- python实现代码行数统计示例分享
- 使用PHPMailer实现邮件发送代码分享
- java简单实现复制粘贴剪切功能代码分享
- JavaScript实现防止网页被嵌入Frame框架的代码分享
- VB实现的16位和32位md5加密代码分享
- ruby实现的文件自删除代码分享
- asp实现检查ip地址是否为内网或者私有ip地址的代码分享
- PHP实现的多彩标签效果代码分享