tcpclient : Add timeout support

git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@4771 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2018-12-17 19:32:33 +00:00
parent 136d037640
commit 3500e719c6

View File

@@ -1,4 +1,5 @@
<?php <?php
/** TCP Client /** TCP Client
* Allow to create TCP connections to a server. * Allow to create TCP connections to a server.
* If both IPv6 and IPv4 are allowed by the server, try in IPv6 then back in * If both IPv6 and IPv4 are allowed by the server, try in IPv6 then back in
@@ -12,6 +13,8 @@
*/ */
class tcpclient class tcpclient
{ {
// PROPERTIES //
// {{{
/** The IPv6 allowed for the server /** The IPv6 allowed for the server
*/ */
private $ipv6 = array (); private $ipv6 = array ();
@@ -40,11 +43,18 @@ class tcpclient
*/ */
private $readMode = "text"; private $readMode = "text";
/** The timeout before aborting the connection
* 30s by default
*/
private $timeout = 30;
// }}}
/** Initialize the object, by setting the name or the IP of the server /** Initialize the object, by setting the name or the IP of the server
* @param string $ipOrName The IP or the name of the server * @param string $ipOrName The IP or the name of the server
* @param integer $port The port of the server to connect * @param integer $port The port of the server to connect
*/ */
public function __construct ($ipOrName, $port) public function __construct ($ipOrName, $port)
// {{{
{ {
$providedIpOrName = $ipOrName; $providedIpOrName = $ipOrName;
if (filter_var ($ipOrName, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) if (filter_var ($ipOrName, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
@@ -93,12 +103,14 @@ class tcpclient
shuffle ($this->ipv6); shuffle ($this->ipv6);
shuffle ($this->ipv4); shuffle ($this->ipv4);
} }
// }}}
/** Set/get the preferIPv4 property /** Set/get the preferIPv4 property
* @param boolean|null $preferIPv4 The preferIPv4 property to set (or to get * @param boolean|null $preferIPv4 The preferIPv4 property to set (or to get
* if null) * if null)
*/ */
public function preferIPv4 ($preferIPv4 = null) public function preferIPv4 ($preferIPv4 = null)
// {{{
{ {
if ($preferIPv4 === null) if ($preferIPv4 === null)
return $this->preferIPv4; return $this->preferIPv4;
@@ -108,11 +120,13 @@ class tcpclient
$this->preferIPv4 = !!$preferIPv4; $this->preferIPv4 = !!$preferIPv4;
return $this; return $this;
} }
// }}}
/** Set/get the read mode : text or binary /** Set/get the read mode : text or binary
* @param string|null $readMode The mode to set (or get if null) * @param string|null $readMode The mode to set (or get if null)
*/ */
public function readMode ($readMode = null) public function readMode ($readMode = null)
// {{{
{ {
if ($readMode === null) if ($readMode === null)
return $this->readMode; return $this->readMode;
@@ -122,11 +136,26 @@ class tcpclient
$this->readMode = $readMode; $this->readMode = $readMode;
return $this; return $this;
} }
// }}}
/** Set/get the timeout
* @param integer|null $timeout The timeout in seconds
*/
public function timeout ($timeout = null)
// {{{
{
if ($timeout === null)
return $this->timeout;
$this->timeout = intval ($timeout);
return $this;
}
// }}}
/** Initialize the connection to the server /** Initialize the connection to the server
* Return the socket * Return the socket
*/ */
public function connect () public function connect ()
// {{{
{ {
if ($this->preferIPv4) if ($this->preferIPv4)
$ips = array_merge ($this->ipv4, $this->ipv6); $ips = array_merge ($this->ipv4, $this->ipv6);
@@ -136,7 +165,8 @@ class tcpclient
{ {
if (filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) if (filter_var ($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
$ip = "[$ip]"; $ip = "[$ip]";
$socket = stream_socket_client ("tcp://$ip:$this->port", $errno, $errstr); $socket = @stream_socket_client ("tcp://$ip:$this->port", $errno, $errstr,
$this->timeout);
if ($socket === false) if ($socket === false)
continue; continue;
$this->socket = $socket; $this->socket = $socket;
@@ -145,6 +175,7 @@ class tcpclient
throw new \Exception ("Can not connect to server $this->ipOrName : ". throw new \Exception ("Can not connect to server $this->ipOrName : ".
$errstr, 500); $errstr, 500);
} }
// }}}
/** Activate the SSL connection. /** Activate the SSL connection.
* Put the socket in blocking mode, as it is mandatory to have SSL connection * Put the socket in blocking mode, as it is mandatory to have SSL connection
@@ -155,6 +186,7 @@ class tcpclient
* server * server
*/ */
public function cryptoEnable ($val, $cryptoMethod = null, $options = array ()) public function cryptoEnable ($val, $cryptoMethod = null, $options = array ())
// {{{
{ {
if ($this->socket === null) if ($this->socket === null)
throw new \Exception ("Can not send to server $this->ipOrName : ". throw new \Exception ("Can not send to server $this->ipOrName : ".
@@ -182,22 +214,26 @@ class tcpclient
substr (strrchr ($php_errormsg, ":"), 1), 500); substr (strrchr ($php_errormsg, ":"), 1), 500);
return $rc; return $rc;
} }
// }}}
/** Send a data to the server. /** Send a data to the server.
* The connection must be established * The connection must be established
* @param mixed $data The data to send * @param mixed $data The data to send
*/ */
public function send ($data) public function send ($data)
// {{{
{ {
if ($this->socket === null) if ($this->socket === null)
throw new \Exception ("Can not send to server $this->ipOrName : ". throw new \Exception ("Can not send to server $this->ipOrName : ".
"The server is not connected", 500); "The server is not connected", 500);
stream_set_timeout ($this->socket, $this->timeout);
$length = strlen ($data); $length = strlen ($data);
$sentLen = @fwrite ($this->socket, $data); $sentLen = @fwrite ($this->socket, $data);
if ($sentLen < $length) if ($sentLen < $length)
throw new \Exception ("Can not send to server $this->ipOrName", 500); throw new \Exception ("Can not send to server $this->ipOrName", 500);
return $sentLen; return $sentLen;
} }
// }}}
/** Read the data from the server. /** Read the data from the server.
* The connection must be established * The connection must be established
@@ -208,10 +244,12 @@ class tcpclient
* @return The content * @return The content
*/ */
public function read ($maxLength = 1024) public function read ($maxLength = 1024)
// {{{
{ {
if ($this->socket === null) if ($this->socket === null)
throw new \Exception ("Can not read from server $this->ipOrName : ". throw new \Exception ("Can not read from server $this->ipOrName : ".
"The server is not connected", 500); "The server is not connected", 500);
stream_set_timeout ($this->socket, $this->timeout);
if ($this->readMode === "text") if ($this->readMode === "text")
{ {
$read = stream_get_line ($this->socket, $maxLength, "\r\n"); $read = stream_get_line ($this->socket, $maxLength, "\r\n");
@@ -226,10 +264,12 @@ class tcpclient
} }
return $read; return $read;
} }
// }}}
/** Disconnect the socket /** Disconnect the socket
*/ */
public function disconnect () public function disconnect ()
// {{{
{ {
if ($this->socket === null) if ($this->socket === null)
throw new \Exception ("Can not disconnect server $this->ipOrName : ". throw new \Exception ("Can not disconnect server $this->ipOrName : ".
@@ -237,11 +277,13 @@ class tcpclient
@stream_socket_shutdown ($this->socket, STREAM_SHUT_RDWR); @stream_socket_shutdown ($this->socket, STREAM_SHUT_RDWR);
$this->socket = null; $this->socket = null;
} }
// }}}
/** Get the connection peer address, peer port and localaddress and localport /** Get the connection peer address, peer port and localaddress and localport
* @return array * @return array
*/ */
public function getInfo () public function getInfo ()
// {{{
{ {
if ($this->socket === null) if ($this->socket === null)
throw new \Exception ("Can not getInfo for server $this->ipOrName : ". throw new \Exception ("Can not getInfo for server $this->ipOrName : ".
@@ -256,12 +298,15 @@ class tcpclient
$address = substr ($name, 0, $pos); $address = substr ($name, 0, $pos);
return array ($address, $port, $localAddress, $localPort); return array ($address, $port, $localAddress, $localPort);
} }
// }}}
/** Get the socket to direct access /** Get the socket to direct access
* @return resource The socket with the client * @return resource The socket with the client
*/ */
public function getSock () public function getSock ()
// {{{
{ {
return $this->socket; return $this->socket;
} }
// }}}
} }