Глюк socket'а?

  • Автор темы Tyler Durden
  • Дата начала

Tyler Durden

Guest
Глюк socket'а?

Привет! Вот код простенького сервачка. Довольно знакомый код. Взят (с небольшими переделками) из примеров patHTTPServer.
PHP:
	    class myClass
	{
	    var $host = '192.168.0.106';
	    var $port = 32280;
	    var $bufSize = 512;
	    var $null = array();
	    var $clientFD = array();
	    var $endChar = "\r\n\r\n";

	    function start()
	    {
	        $this->initFD = @socket_create( AF_INET, SOCK_STREAM, 0 );

	        if( !$this->initFD )
	        {
	            $this->logMsg( "Couldn't create socket" );
	            exit();
	        }

	        socket_set_option( $this->initFD, SOL_SOCKET, SO_REUSEADDR, 1 );

	        if( !@socket_bind( $this->initFD, $this->host, $this->port ) )
	        {
	            @socket_close( $this->initFD );
	            $this->logMsg( "Could not bind socket ( ".$this->getLastSocketError( $this->initFD )." )" );
	            exit();
	        }

	        if( !@socket_listen( $this->initFD, SOMAXCONN ) )
	        {
	            $this->logMsg( "Could not listen ( ".$this->getLastSocketError( $this->initFD )." )" );
	            exit();
	        }

	        set_time_limit( 0 );

	        $this->logMsg( "Server Started!" );

	        while( true )
	        {
	            $readFDs = array();
	            array_push( $readFDs, $this->initFD );

	            for( $i = 0; $i < sizeof( $this->clientFD ); $i++ )
	            {
		            if( isset( $this->clientFD[$i] ) )
		            {
		            	array_push( $readFDs, $this->clientFD[$i] );
		            }
		        }

	            $ready = @socket_select( $readFDs, $this->null, $this->null, null );

	            if( $ready === false )
	            {
	                $this->logMsg( "Socket_select failed" );
	                $this->shutDown();
	            }

                if( in_array( $this->initFD, $readFDs ) )
                {
                    $newClient = $this->acceptConn( $this->initFD );
                    if( --$ready <= 0 ) continue;
                }

                for( $i = 0; $i < sizeof( $this->clientFD ); $i++ )
                {
                    if( !isset( $this->clientFD[$i] ) ) continue;
                    if( in_array( $this->clientFD[$i], $readFDs ) )
                    {
                        $data = $this->readFromSocket( $i );
                        if( !$data )
                        {
                            $this->closeConn( $i );
                            $this->logMsg( "Connection closed by peer!" );
                        }
                    }
                }
	        }
	    }

	    function acceptConn( &$socket )
	    {
	        for( $i = 0 ; $i <= sizeof( $this->clientFD ); $i++ )
	        {
	            if( !isset( $this->clientFD[$i] ) )
	            {
	                $this->clientFD[$i] = socket_accept( $socket );
	                socket_setopt( $this->clientFD[$i], SOL_SOCKET, SO_REUSEADDR, 1 );
	                $this->logMsg( "New connection: " . $i );
	                return $i;
	            }
	        }
	    }

	    function readFromSocket( $sockID )
	    {
	        $data = '';
	        while( $buf = @socket_read( $this->clientFD[$sockID], $this->bufSize ) )
	        {
	            $data = $data . $buf;
	            $endString = substr( $buf, - strlen( $this->endChar ) );
	            if( $endString == $this->endChar ) break;
	        }
	        return $data;
	    }

	    function closeConn( $sockID )
	    {
	    	if( !isset( $this->clientFD[$sockID] ) ) return;
            @socket_close( $this->clientFD[$sockID] );
            $this->clientFD[$sockID] = null;
            $this->logMsg( "Closed connection: " . $sockID );
	    }

	    function logMsg( $msg )
	    {
            echo date( "d.m.Y H:i:s" ) . " " . $msg . "\n";
            flush();
	    }

	    function getLastSocketError( &$fd )
	    {
	        $lastError = socket_last_error( $fd );
	        return "msg: " . socket_strerror( $lastError ) . " / Code: " . $lastError;
	    }

	    function shutDown()
	    {
	        $maxFD = sizeof( $this->clientFD );
	        for( $i = 0; $i < $maxFD; $i++ )
	        {
	        	$this->closeConn( $i );
	        }
	        @socket_close( $this->initFD );
	        $this->logMsg( "Server stopped" );
	        exit;
	    }
	}

	$server = new myClass();
	$server->start();
Ждет входящих соединений на порт 32280, получив, держит постоянный коннект и может вывести в сокет какие-либо данные. Открываю броузер и набираю в строке адреса "http://192.168.0.106:32280". Соединяется с сервером. Все замечательно, казалось бы, но возникает непонятная мне вещь. Ровно через один час после установления соединения, это соединение разрывается... Вот лог того, что пишет сервер:

14.02.2005 21:32:45 Server Started!
14.02.2005 21:32:58 New connection: 0
14.02.2005 22:32:58 Closed connection: 0
14.02.2005 22:32:58 Connection closed by peer!

Тестировал прогу под виндами (WinXP, Apache 1.3.31, PHP 4.3.9), а также под Линухой (RedHat7.3, kern. 2.4.18, Apache 1.3.31, PHP 4.3.9). Результат один и тот же. Расскажите, пожалуйста, в чем может быть причина? Спасибо.
 

Кром

Новичок
>Расскажите, пожалуйста, в чем может быть причина?

Броузер разрывает соединение.
 

Tyler Durden

Guest
А как этого можно избежать? Может необходимо послать броузеру какие-нить header'ы? Как-то можно указать броузеру, чтобы он не разрывал данного соединения??? Может Connection: keep-alive?
 

Кром

Новичок
А зачем этого избегать? То что броузер рвет соединение, это нормальное явление.
 

Tyler Durden

Guest
А если надо применить такой подход к разработкам чат-приложений? Там соединения не должны разрываться!

Так все-таки, этого как-то можно избежать? Если есть определенное число, в данном случае - 3600 секунд, то должно же оно как-то настраиваться? Или я не прав?
 
Сверху