php.de

Zurück   php.de > Webentwicklung > Software-Design

Software-Design Diskussionen auf Profi-Niveau: PHP Lösungen auf konzeptioneller Ebene

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 13.05.2010, 17:38  
Benutzer
 
Registriert seit: 04.01.2009
Beiträge: 43
Deltachaos befindet sich auf einem aufstrebenden Ast
Standard

Also Hardware:

Intel Q9550, 4x 2.83 GHz, 8.192 MB DDRII RAM
OS: Debian Lenny

Server Script:
PHP-Code:
#!/usr/bin/php
<?php
    $port 
1338;
           

    class 
redServerClient
    
{
    
        private 
$redServerSocket;
        private 
$commandcache '';
        public 
$get_history = array();
        public 
$send_history = array();
        public 
$handle;
        public 
$id;
        public 
$lastused;
        public 
$connected;
        public 
$data = array();
        
        public function 
__construct($redServerSocket$handle)
        {
            
$this->redServerSocket $redServerSocket;
            
$this->handle $handle;
            
$this->id $redServerSocket->getIdFromHandle($handle);
            
            
$this->connected time();
            
$this->lastused time();
            
        }
        
        public function 
addCache($string)
        {
            
$this->lastused time();
            
$this->commandcache .= $string;
        }
        
        public function 
getCache()
        {
            return 
$this->commandcache;
        }
        
        public function 
clearCache()
        {
            if(
is_array($this->get_history))
                
$this->get_history[] = substr($this->commandcache0, (strlen($this->redServerSocket->end) * -1));
            
$this->commandcache '';
        }
        
        public function 
disconnect($code 3000)
        {
            @
socket_shutdown($this->handle);
            @
socket_close($this->handle);
            
$this->redServerSocket->callClientDisconnect($this->id$code);
            
$this->redServerSocket->unsetClient($this->id);
            return 
TRUE;
        }
        
        public function 
write($data)
        {
            
$this->redServerSocket->callDataSend($this->id$data);
            if(
is_array($this->send_history))
                
$this->send_history[] = $data;
            return 
socket_write($this->handle$data);
        }
        
        public function 
send($data)
        {
            return 
$this->write($data);
        }
        
        public function 
lastErrorCode()
        {
            return 
socket_last_error($this->handle);
        }
        
        public function 
lastErrorString()
        {
            return 
socket_strerror($this->lastErrorCode());
        }
        
    }
    
    abstract class 
redServerSocket
    
{
    
    
        private 
$code = array(
            
'from_api'            => 3000
            
'timeout'            => 3001
            
'connection_closed'        => 3002,
            
'connection_refused'        => 3003
        
);
        private 
$mainsocket NULL;
        private 
$clients = array();
        
        protected 
$host 0;
        protected 
$port 0;
        protected 
$timeout NULL;
        
        public 
$end NULL;
        
        protected function 
onDataRecieve($clientObj$data)
        {
            return 
TRUE;
        }

        protected function 
onDataSend($clientObj$data)
        {
            return 
TRUE;
        }        
        
        protected function 
onClientConnect($clientObj)
        {
            return 
TRUE;
        }
        
        protected function 
onClientDisconnect($clientObj$code)
        {
            return 
TRUE;
        }
        
        protected function 
onSocketReady($host$port)
        {
        }
        
        protected function 
onSocketError($error$client false)
        {
        }
        
        public function 
__construct($port NULL$host NULL)
        {
            if(
$this->end === NULL)
                
$this->end chr(4);
            if(
false == ($this->mainsocket = @socket_create(AF_INETSOCK_STREAMSOL_TCP)))
            {
                
$this->onSocketError($this->lastErrorCode());
            }
            else
            {
                @
socket_set_option($this->mainsocketSOL_SOCKETSO_REUSEADDR1);
                if(
$port !== NULL)
                    
$this->port $port;
                if(
$host !== NULL)
                    
$this->host $host;
                if(
false == ($ret =@socket_bind($this->mainsocket$this->host$this->port)))
                {
                    
$this->onSocketError($this->lastErrorCode());
                }
                else
                {
                    
$ret socket_listen($this->mainsocket2000);
                    
$this->onSocketReady($this->host$this->port);
                }
            }
        }
        
        public function 
callDataSend($id$data)
        {
            if(!
is_object($id))
                
$id $this->clients[$id];
            
$this->onDataSend($id$data);
        }
        
        public function 
callClientDisconnect($id$code)
        {
            if(!
is_object($id))
                
$id $this->clients[$id];
            
$this->onClientDisconnect($id$code);
        }
        
        public function 
getIdFromHandle($handle)
        {
            
$str = (string)$handle;
            
$str substr($str13);
            return (int)
$str;
        }
        
        public function 
getClients()
        {
            return 
$this->clients;
        }
        
        public function 
unsetClient($client)
        {
            unset(
$this->clients[$client]);
        }
        
        public function 
clientCheck()
        {
            
$localClients = array();
            foreach(
$this->clients as $num => $clientObj)
            {
            
                if(
$this->timeout !== NULL && $clientObj->lastused time() - $this->timeout && $this->onClientDisconnect($clientObj$this->code['timeout']))
                    
$clientObj->disconnect($this->code['timeout']);
                else
                    
$localClients[$clientObj->id] = $clientObj->handle;
            }
            
            
$set_r array_merge((array)$this->mainsocket$localClients);
            
$set_w NULL;
            
$set_e $localClients;
            
            
//    Check for new Data.
            //    If the mainsocket in the array $set_r
            //    then is there a new Client!
            //    If not then is there new Data from the Socket in the Array
            
            
if( ( $ret =@socket_select($set_r$set_w $set_e 1) ) > )
            {
                foreach(
$set_r as $data)
                {
                    if(
$data == $this->mainsocket//Is it the mainsocket there are new clients in it!
                    
{
                        
$newclient = @socket_accept($this->mainsocket);
                        if(
$newclient)
                        {
                            
$id $this->getIdFromHandle($newclient);
                            
$clientObj = new redServerClient($this$newclient);
                            
$this->clients[$id] = $clientObj;
                            if(
$this->onClientConnect($clientObj) === FALSE)
                                
$clientObj->disconnect($this->code['connection_refused']);
                        }
                        else
                            
$this->onSocketError($this->lastErrorCode());
                    }
                    else
                    {
                        
$data_read socket_read($data1024);
                        
$id $this->getIdFromHandle($data);
                        if(
$data_read === false)
                        {
                            
$ret $this->onSocketError($this->lastErrorCode(), $this->clients[$id]);
                            if(!
$ret)
                                
$this->clients[$id]->disconnect($this->code['from_api']);
                        }
                        else
                        {
                            if(
strlen($data_read) > && isset($this->clients[$id]))
                            {
                                
$this->clients[$id]->lastaction time();
                                
$this->clients[$id]->addCache($data_read);
                                
$endstr_len strlen($this->end);
                                if(
substr($this->clients[$id]->getCache(), ($endstr_len * -1), $endstr_len) === $this->end)
                                {
                                    
$this->onDataRecieve($this->clients[$id], substr($this->clients[$id]->getCache(), 0, ($endstr_len * -1)));
                                    
$this->clients[$id]->clearCache();
                                }
                            }
                            else
                                
$this->clients[$id]->disconnect($this->code['connection_closed']);
                        }
                    }
                }
                foreach(
$set_e as $handle//Oh, these Clients have an ugly Error. I kick them from my List!
                
{
                    
$id $this->getIdFromHandle($handle);
                    
$this->clients[$id]->disconnect($this->code['connection_closed']);
                }
            }
        }
        
        public function 
lastErrorCode()
        {
            return 
socket_last_error($this->mainsocket);
        }
        
        public function 
lastErrorString()
        {
            return 
socket_strerror($this->lastErrorCode());
        }
    }
    

    
    
/*
        Metoden der Clients Objekte:
        
        public $get_history = array();
        //echo "Dein letztes Komando war: $get_history[0]"
        public $send_history = array();
        //echo "Ich habe dir zuletzt gesendet: $send_history[0]"
        public $handle; //Client Socket Handle. Siehe: http://php.net/manual/de/function.socket-accept.php
        public $id; //Client ID
        public $lastused; //Unix Timestamp der letzten Client Reaktion.
        public $connected; //Unix Timestamp des Verbindungszeitpunktes
        public $data = array(); //Ein Array zum Speichern von Session Variablen
        
        
        public function addCache($string) //Fügt $string zum commandcache hinzu
        public function getCache() //Gibt den aktuellen commandcache zurück
        public function clearCache() //Löscht den aktuellen commandcache
        
        public function disconnect($code = 3000) //Schliest Verbindung mit Fehlercode
        public function write($data) //Sendet Daten an Client. Rückgabe von function: http://de3.php.net/manual/en/function.socket-write.php
        public function send($data) //Alias für write($data)
        
        public function lastErrorCode() //Alias für: socket_last_error($this->handle)
        public function lastErrorString() //Alias für: socket_strerror(socket_last_error($this->handle))
    
    */
    
    
class Server extends redServerSocket
    
{
        
        
//$this->end = '\n' //Begrenzer der einzelnen Komandos. Standart ist: chr(4) (EOT)
        //$this->timeout = 3600; //Zeit in der Client Nachrichten senden muss bevor er aus der Liste geworfen wird.
                     //NULL deaktiviert das Timeout. Standart ist: NULL
        
        //public function lastErrorCode() //Alias für: socket_last_error($this->mainsocket)
        //public function lastErrorString() //Alias für: socket_strerror(socket_last_error($this->mainsocket))
        //public function getClients() //return $this->clients.
        
        
protected function onDataRecieve($clientObj$data)
        {
            echo 
"onDataRecieve [" $clientObj->id "]: " $data "\n";
            
//$clients = $this->getClients();
            //foreach($clients as $id => $clientsObj_)
            //    $clientsObj_->write('[' . $clientObj->id . ']: ' . $data);
            
        
}

        protected function 
onDataSend($clientObj$data)
        {
            echo 
"onDataSend [" $clientObj->id "]: " $data "\n";
        }        
        
        protected function 
onClientConnect($clientObj)
        {
            echo 
"onClientConnect [" $clientObj->id "]\n";
            
$clientObj->get_history NULL//Deaktiviert die get_history
            
$clientObj->send_history NULL//Deaktiviert die send_history
            
return FALSE//Wenn return false wird der client abgelehnt
        
}
        
        protected function 
onClientDisconnect($clientObj)
        {
            echo 
"onClientDisconnect [" $clientObj->id "]\n";
        }
        
        protected function 
onSocketReady($host$port)
        {
            echo 
"Socket ready!!\n";
        }
        
        protected function 
onSocketError($errorcode$clientObj false)
        {
            if(
$clientObj !== false)
                echo 
"Error [" $clientObj->id "]" $this->lastErrorString(); //Fehler von Client
            
else
                echo 
"Error" $this->lastErrorString(); //Fehler von Mainsocket
            //return true; //läst den Client, sollte es ein Fehler sein bei dem er normalerweise disconnectet wird, in der Liste;
        
}
    
    }
    
    echo    
"Server startet on Port: ".$port."\n" .
        
"On Liux and Windows Systems you can connect to the server with:\n" .
        
"telnet <IP> ".$port."\n" .
        
"You can disconnect by close the Terminal\n" .
        
"You can shutdown the Server by press CTRL + C in the Server Terminal\n" .
        
"GL & HF!\n" .
        
"#######################################################################\n";
    
    
$host NULL;
    
$socket = new Server($port$host); //Port und Host. Wenn Host === NULL dann hört der Server auf alle IP Adressen des Hosts
    
    
while(true)
    {
        
$socket->clientCheck(); //Prüft auf neue Nachrichten. 
    
}

?>
Client Code:
PHP-Code:
<?php
$soks 
= array()
$i 0;
while(
true)
{
$sock[] = fsockopen("cubexsports.de"1338$errno$errstr30);
$i++;
echo 
$i "\n";

}
?>
Deltachaos ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 14.05.2010, 12:00  
Erfahrener Benutzer
 
Registriert seit: 12.05.2005
Beiträge: 1.038
PHP-Kenntnisse:
Fortgeschritten
notyyy befindet sich auf einem aufstrebenden Ast
Standard

ein weiteres gigantisches Problem was ich hier sehe, was passiert wenn ein paar Clients irre langsam sind?
notyyy ist offline   Mit Zitat antworten
Alt 14.05.2010, 12:47  
Erfahrener Benutzer
 
Registriert seit: 17.07.2009
Beiträge: 223
PHP-Kenntnisse:
Fortgeschritten
Tiberius zeigte ein beschämendes Verhalten in der Vergangenheit
Tiberius eine Nachricht über ICQ schicken
Standard

was soll dann sein? Daten die geschrieben werden können werden geschrieben, alles andere bleibt im Buffer(App/Socket) und muss nach und nach raus
Tiberius ist offline   Mit Zitat antworten
Alt 17.05.2010, 07:45  
Benutzer
 
Registriert seit: 05.06.2008
Beiträge: 78
Normalo befindet sich auf einem aufstrebenden Ast
Normalo eine Nachricht über ICQ schicken
Standard

4 Prozessorkerne für 1 Thread ^^
Normalo ist offline   Mit Zitat antworten
Alt 17.05.2010, 09:57  
Erfahrener Benutzer
 
Registriert seit: 12.05.2005
Beiträge: 1.038
PHP-Kenntnisse:
Fortgeschritten
notyyy befindet sich auf einem aufstrebenden Ast
Standard

man könnte mal ausprobieren zu forken und memcache zu verwenden

edit:

ich habe mal testweise versucht den socketserver ans laufen zu bekommen, bei mir ist er völlig regungslos und nimmt keine verbindungen an....

PHP-Code:
while(true
    { 
        
$socket->clientCheck(); //Prüft auf neue Nachrichten. 
        
ob_flush(); // hilfreich ;)
    


Geändert von notyyy (17.05.2010 um 11:23 Uhr).
notyyy ist offline   Mit Zitat antworten
Alt 17.05.2010, 14:59  
Erfahrener Benutzer
 
Registriert seit: 12.05.2005
Beiträge: 1.038
PHP-Kenntnisse:
Fortgeschritten
notyyy befindet sich auf einem aufstrebenden Ast
Standard

ich habe mir das ganze mal genauer angeguckt und muss sagen, dass ich wirklich positiv überrascht bin wie performant man einen Socketserver so gestalten kann.

mit den threads stimmt ja so auch nicht wirklich, da php hier ja asynchron die Sockets raus schiebt. Extrem lustig ist, dass mein PHP Socketserver so schnell senden kann, dass das Java programm abrotzt, er selber aber noch schnarcht

vielleicht werde ich neben meinem C# Webserver ein wenig weiter mit PHP spielen
notyyy ist offline   Mit Zitat antworten
Alt 24.05.2010, 01:09  
Benutzer
 
Registriert seit: 04.01.2009
Beiträge: 43
Deltachaos befindet sich auf einem aufstrebenden Ast
Standard

Wie hast du den diesen Server versucht ans laufen zu bringen?

du weist das du das ganze per CLI Starten musst ne.
Eingentlich reicht ein:

chmod +x datei.php
./datei.php

PS: ist auf einem Linux Systhem getestet.
Deltachaos ist offline   Mit Zitat antworten
Alt 25.05.2010, 09:30  
Erfahrener Benutzer
 
Registriert seit: 12.05.2005
Beiträge: 1.038
PHP-Kenntnisse:
Fortgeschritten
notyyy befindet sich auf einem aufstrebenden Ast
Standard

habe es natürlich via CLI gestartet (unter windows). Er tut bei mir einfach nichts.

ich habe ein wenig selber rum implementiert und es wunderbar ans laufen bekommen.

ich habe keinen telnet client genutzt sondern "echte sockets".
notyyy ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
[Erledigt] Kommunikation zwischen Clients nicktight PHP-Fortgeschrittene 13 11.04.2010 16:51
php5 & sockets fre@ky PHP-Fortgeschrittene 16 25.08.2008 11:41
Arbeiten mit Sockets vollkommenegal PHP-Fortgeschrittene 20 29.11.2007 11:00
Geschwindigkeit von Sockets Sascha Bahl PHP-Fortgeschrittene 17 05.03.2007 21:39
Location des Clients fmueller PHP Tipps 2006 9 05.03.2006 01:09
PHP, Sockets AND Server/Client PHP Tipps 2006 3 13.01.2006 17:44
PHP Scrip.t nur von bestimmten Clients aufrufen dh1sbg PHP-Fortgeschrittene 6 09.01.2006 16:56
eine tabelle - mehrere clients Datenbanken 2 31.08.2005 11:27
Von Server auf die Platte des Clients zugreifen PHP Tipps 2005-2 6 21.08.2005 15:56
Verständnisfragen zu persistenten und blockenden Sockets HStev PHP-Fortgeschrittene 0 19.08.2005 11:37
Php Sockets Tutorial [codewalkers.com] endet in Timeout Cmon PHP Tipps 2005-2 2 02.08.2005 20:57
Erkennung der Systemsprache des Clients PHP Tipps 2004-2 4 14.12.2004 21:03
[Erledigt] Sockets Server, Hosting und Workstations 3 08.09.2004 16:38
Den Gerätemanager des Clients auslesen PHP-Fortgeschrittene 4 16.07.2004 11:01
Sockets unter PHP PHP Tipps 2004 1 08.07.2004 16:32

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
php sockets, php socket client, php socket array verbundene clients, socket $set_r = array_merge, php socket read liest keine null, php echo server socket, php socket server clients, php socket zwischenspeichern, sockets php, php socket_accept handle error, php mehrere socket clients in einer datei, php socket connect echtes timeout, http://www.php.de/software-design/67399-php-sockets-viele-clients-handeln-5.html, php socket class, php socket server, php socket get data, socket server starten cli php, php socket client langsam, php socket handler, php socket write listen

Alle Zeitangaben in WEZ +2. Es ist jetzt 00:38 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum