<?php 
 
/** 
 * This file is part of the PHP Generics package. 
 * 
 * @package Generics 
 */ 
namespace Generics\Socket; 
 
/** 
 * This class provides a basic client socket implementation 
 * 
 * @author Maik Greubel <[email protected]> 
 */ 
class ServerSocket extends Socket 
{ 
 
    /** 
     * Create a new server socket 
     * 
     * @param Endpoint $endpoint 
     *            The endpoint to use 
     * 
     * @throws SocketException In case of creation of socket has failed or socket options could not be set. 
     */ 
    public function __construct(Endpoint $endpoint) 
    { 
        parent::__construct($endpoint); 
        if (! @socket_set_option($this->handle, SOL_SOCKET, SO_REUSEADDR, 1)) { 
            $code = socket_last_error($this->handle); 
            throw new SocketException(socket_strerror($code), array(), $code); 
        } 
    } 
 
    /** 
     * Creates a service at the given endpoint 
     * 
     * @throws SocketException in case of it is not possible to serve due to binding or listening error 
     */ 
    public function serve(ServiceCallback $callback) 
    { 
        $this->bind(); 
         
        $this->listen(); 
         
        $runOn = true; 
         
        while ($runOn) { 
            $clientHandle = @socket_accept($this->handle); 
             
            if (! is_resource($clientHandle)) { 
                $code = socket_last_error($this->handle); 
                throw new SocketException(socket_strerror($code), array(), $code); 
            } 
             
            $address = null; 
            $port = 0; 
            if (! @socket_getpeername($clientHandle, $address, $port)) { 
                $code = socket_last_error($clientHandle); 
                throw new SocketException(socket_strerror($code), array(), $code); 
            } 
             
            $client = new ClientSocket(new Endpoint($address, $port), $clientHandle); 
             
            $runOn = boolval($callback->callback($client)); 
        } 
    } 
 
    /** 
     * Bind the server socket to the given endpoint 
     * 
     * @throws SocketException in case of binding has failed 
     */ 
    private function bind() 
    { 
        if (! @socket_bind($this->handle, $this->endpoint->getAddress(), $this->endpoint->getPort())) { 
            $code = socket_last_error($this->handle); 
            throw new SocketException(socket_strerror($code), array(), $code); 
        } 
    } 
 
    /** 
     * Listen to the binded socket endpoint 
     * 
     * @throws SocketException in case of listening is not possible 
     */ 
    private function listen() 
    { 
        if (! @socket_listen($this->handle, 5)) { 
            $code = socket_last_error($this->handle); 
            throw new SocketException(socket_strerror($code), array(), $code); 
        } 
    } 
} 
 
 |