[TASK] Moved the project to namespaces.

[TASK] Removed all the protocol handlers.
[TASK] Clients are no longer part of the SocketFramework itself.
[TASK] The Framework provides an "interface" to external clients - the ClientDispatcher.
[TASK] Added the Core package and added a better ClassLoader.
[TASK] Created a bootstrap module to include in other projects.
[TASK] Cleaned up comments, reformatted them.
This commit is contained in:
Jan Philipp Timme
2011-12-03 12:43:43 +01:00
parent 8de6bb29b6
commit 16ff75eb1d
32 changed files with 573 additions and 541 deletions
@@ -0,0 +1,246 @@
<?php
namespace JPT\SocketFramework\Socket;
/**
* The SocketHandler class will handle a single socket.
* It takes care of the very basic socket functions.
*
* @author jpt
* @package Socket
*/
class SocketHandler {
/**
* Socket ressource
*
* @var ressource
*/
protected $socket;
/**
* @var boolean
*/
protected $isConnected;
/**
* @var boolean
*/
protected $isBound;
/**
* @var boolean
*/
protected $isListening;
/**
* Default constructor. Sets the socket.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @param ressource $socket
* @return void
*/
public function __construct($socket) {
if(is_resource($socket) === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("Invalid socket ressource!", 1289663108);
$this->socket = $socket;
$this->isBound = FALSE;
$this->isConnected = FALSE;
$this->isListening = FALSE;
}
/**
* Destructor. Closes socket.
*
* @return void
*/
public function __destruct() {
$this->close();
}
/**
* Returns socket.
*
* @return ressource
*/
public function getSocket() {
return $this->socket;
}
/**
* @return boolean
*/
public function isConnected() {
return $this->isConnected;
}
/**
* Sets isConnected-flag.
*
* @param boolean $connected
* @return void
*/
public function setConnected($connected) {
$this->isConnected = $connected;
}
/**
* @return boolean
*/
public function isListening() {
return $this->isListening;
}
/**
* Connects to a specified address.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @param string $address
* @param int $port
* @return void
*/
public function connect($address, $port) {
if($this->isConnected === TRUE) throw new \JPT\SocketFramework\Exception\SocketException("Socket is already connected!", 1289663170);
$result = socket_connect($this->socket, $address, $port);
if($result === FALSE) $this->handleSocketError();
$this->isConnected = TRUE;
}
/**
* Binds the socket to an address + port.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @param string $address
* @param int $port
* @return void
*/
public function bind($address, $port) {
if($this->isBound === TRUE) throw new \JPT\SocketFramework\Exception\SocketException("Socket is already bound!", 1289663212);
$result = socket_set_option($this->socket, \SOL_SOCKET, \SO_REUSEADDR, 1);
if($result === FALSE) $this->handleSocketError();
$result = socket_bind($this->socket, $address, $port);
if($result === FALSE) $this->handleSocketError();
$this->isBound = TRUE;
}
/**
* Let's the socket listen for incoming connections.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @return void
*/
public function listen() {
if($this->isBound === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("Cannot listen on unbound socket!", 1289663220);
$result = socket_listen($this->socket);
if($result === FALSE) $this->handleSocketError();
$this->isListening = TRUE;
}
/**
* Tells the SocketHandler that he got accepted.
*
* @return void
*/
public function hasBeenAccepted() {
$this->isConnected = TRUE;
}
/**
* Accepts a connection to a socket that is bound and listens.
* The ressource has to be added to the SocketPool manually.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @return ressource
*/
public function accept() {
if($this->isBound === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("Cannot accept connections from unbound socket!", 1289663239);
if($this->isListening === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("Cannot accept connections from socket that is not listening!", 1289663241);
$accept = socket_accept($this->socket);
if($accept === FALSE) $this->handleSocketError();
return $accept;
}
/**
* Returns ip + port of the remote socket.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @return string
*/
public function getRemoteName() {
if($this->isConnected === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("Socket not connected, cannot retrieve remote name!", 1289928192);
$result = socket_getpeername($this->socket, $address, $port);
if($result === FALSE) $this->handleSocketError();
return $address . ":" . $port;
}
/**
* Returns ip + port of the local socket.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @return string
*/
public function getLocalName() {
if($this->isBound === FALSE ^ $this->isConnected === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("Socket is not bound or connected, no local name available!", 1289928256);
$result = socket_getsockname($this->socket, $address, $port);
if($result === FALSE) $this->handleSocketError();
return $address . ":" . $port;
}
/**
* Writes data to the socket.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @param string $data
* @return void
*/
public function write($data) {
$result = socket_write($this->socket, $data);
if($result === FALSE) $this->handleSocketError();
}
/**
* Reads data from the socket.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @param int $length
* @return string
*/
public function read($length = 16384) {
$result = socket_read($this->socket, $length, \PHP_BINARY_READ);
if($result === FALSE) $this->handleSocketError();
return $result;
}
/**
* Shuts the socket down after waiting a bit (waiting might be optional).
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @return void
*/
public function close() {
usleep(100000); //we'll wait here since socket_shutdown _might_ fail without it.
if($this->isConnected === TRUE) {
$result = socket_shutdown($this->socket);
if($result === FALSE) $this->handleSocketError();
}
if(is_resource($this->socket)) {
$result = socket_close($this->socket);
if($result === FALSE) $this->handleSocketError();
}
$this->isConnected = FALSE;
}
/**
* Gets last error from socket.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @return void
*/
protected function handleSocketError() {
if(is_resource($this->socket) === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("No socket resource available!", 1290954177);
$errno = socket_last_error($this->socket);
$error = socket_strerror($errno);
socket_clear_error();
$errormsg = "[" . $errno . "] " . $error;
throw new \JPT\SocketFramework\Exception\SocketException("A socket error occured: " . $errormsg, 1289663360);
}
}
?>
@@ -0,0 +1,111 @@
<?php
namespace JPT\SocketFramework\Socket;
/**
* The SocketPool class that will handle all the sockets.
* Manages a pool of socket ressources with socket_select().
*
* @author jpt
* @package Socket
*/
class SocketPool {
/**
* Pool that contains socket ressources.
*
* @var array
*/
protected $sockets;
/**
* Creates sockets.
*
* @return void
*/
public function __construct() {
$this->sockets = array();
}
/**
* Closes all connections.
*
* @return void
*/
public function __destruct() {
unset($this->sockets);
}
/**
* Returns the amount of active sockets.
*
* @return int
*/
public function countSockets() {
return count($this->sockets);
}
/**
* Adds a socket to the pool.
*
* @param ressource $addSocket
* @return void
*/
public function addSocket($addSocket) {
array_push($this->sockets, $addSocket);
}
/**
* Removes the given socket from the pool.
* The socket will be shutdown.
*
* @param ressource $removeSocket
* @return void
*/
public function removeSocket($removeSocket) {
foreach($this->sockets AS $key=>$socket) {
if($socket !== $removeSocket) {
continue;
} else {
unset($socket);
unset($this->sockets[$key]);
break;
}
}
}
/**
* Creates a new TcpSocket and adds it to the pool.
*
* @throws \JPT\SocketFramework\Exception\SocketException
* @param boolean $IPv6 will determine whether the socket uses IPv4 or IPv6.
* @return ressource
*/
public function createTcpSocket($IPv6 = FALSE) {
$domain = ($IPv6) ? \AF_INET6 : \AF_INET;
$socket = socket_create($domain, \SOCK_STREAM, \SOL_TCP);
socket_set_block($socket);
if($socket === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("socket_create() failed!", 1290273709);
$this->addSocket($socket);
return $socket;
}
/**
* Returns an array of sockets one can read from.
*
* @param array $read
* @param array $write
* @param array $except
* @param int $timeout
* @throws \JPT\SocketFramework\Exception\SocketException
* @return array
*/
public function select($read, $write, $except, $timeout = NULL) {
$n = socket_select($read, $write, $except, $timeout);
if($n === FALSE) throw new \JPT\SocketFramework\Exception\SocketException("socket_select() failed! - Error: " . socket_strerror(socket_last_error()), 1290273693);
if($n === 0) return array("read" => array(), "write" => array(), "except" => array());
return array("read" => $read, "write" => $write, "except" => $except);
}
}
?>