使用php搭建socket,用PHP的Socket建立自己的聊天室服务器

class patServer{

var $systemVars =

array(

"appName" =>

"patServer",

"appVersion" =>

"1.1",

"author" =>

array("Stephan Schmidt ",

)

);

var

$port = 10000;

var

$domain = "localhost";

var $maxClients = -1;

var

$readBufferSize = 128;

var $readEndCharacter =

"\n";

var $maxQueue = 500;

var

$debug = true;

var $debugMode = "text";

var $debugDest = "stdout";

var

$null = array();

var $clientFD = array();

var $clientInfo = array();

var $serverInfo = array();

var $clients = 0;

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 );

}

function setMaxClients( $maxClients ){

$this->maxClients = $maxClients;

}

function setDebugMode( $debug, $dest = "stdout" ){

if( $debug === false ){

$this->debug = false;

return

true;

}

$this->debug =

true;

$this->debugMode = $debug;

$this->debugDest = $dest;

}

function start(){

$this->initFD =

@socket_create(

AF_INET, SOCK_STREAM, 0 );

if(

!$this->initFD )

die(

"patServer: Could 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: Could not bind socket to

".$this->domain." on port

".$this->port." (

".$this->getLastSocketError(

$this->initFd )." )." );

}

// listen on selected

port

if(!@socket_listen(

$this->initFD, $this->maxQueue )

)

die(

"patServer: Could not listen (

".$this->getLastSocketError(

$this->initFd )." )." );

$this->sendDebugMessage( "Listening on port

".$this->port.". Server started at ".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

server will be sutdown 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 connections

if( $this->maxClients > 0 ){

if( $this->clients >

$this->maxClients ){

$this->sendDebugMessage( "Too many 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( $this->clientFD ); $i++

){

if( !isset( $this->clientFD[$i] ) )

continue;

if( in_array( $this->clientFD[$i], $readFDs )

){

$data = $this->readFromSocket( $i );

// empty data => connection was closed

if( !$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 );

}

}

}

}

}

function 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( "Could not read from client

".$clientId." ( ".$this->getLastSocketError(

$this->clientFD[$clientId] )." )." );

return $data;

}

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->sendDebugMessage( "New connection ( ".$i." )

from ".$peer_host." on port ".$peer_port );

if( method_exists( $this, "onConnect" ) )

$this->onConnect( $i );

return $i;

}

}

}

function isConnected( $id ){

if( !isset(

$this->clientFD[$id] ) )

return

false;

return true;

}

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--;

}

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;

}

function getClients(){

return

$this->clients;

}

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( "Could not write

'".$data."' client ".$clientId." (

".$this->getLastSocketError(

$this->clientFD[$clientId] )." )." );

}

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( "Could not write

'".$data."' client ".$i." (

".$this->getLastSocketError(

$this->clientFD[$i] )." )." );

}

}

}

function getClientInfo( $clientId ){

if( !isset(

$this->clientFD[$clientId] ) ||

$this->clientFD[$clientId] == NULL )

return

false;

return

$this->clientInfo[$clientId];

}

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;

}

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();

?>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值