1+ <?php
2+ 3+ defined('CONNECTED') ? CONNECTED : define("CONNECTED", true);
4+ defined('DISCONNECTED')? DISCONNECTED : define("DISCONNECTED", false);
5+ 6+ /**
7+ * Socket class
8+ *
9+ * This class can be used to connect to external sockets and communicate with the server
10+ *
11+ * @author Tom Reitsma <treitsma@rse.nl>
12+ * @version 0.6
13+ */
14+ 15+ if(!class_exists('Socket')){
16+ 17+ Class Socket
18+ {
19+ /**
20+ * @var singleton $instance
21+ * @desc Singleton var
22+ */
23+ private static $instance;
24+ 25+ /**
26+ * @var resource $connection
27+ * @desc Connection resource
28+ */
29+ private $connection = null;
30+ 31+ /**
32+ * @var string $connectionState
33+ * @desc
34+ */
35+ private $connectionState = DISCONNECTED;
36+ 37+ /**
38+ * @var int $defaultHost
39+ * @desc Default ip address to connect to
40+ */
41+ private $defaultHost = "192.211.62.21";
42+ 43+ /**
44+ * @var int $defaultPort
45+ * @desc Default port to connect to
46+ */
47+ private $defaultPort = 110;
48+ 49+ /**
50+ * @var float $defaultTimeout
51+ * @desc Default timeout for connection to a server
52+ */
53+ private $defaultTimeout = 10;
54+ 55+ /**
56+ * @var bool $persistentConnection
57+ * @desc Determines wether to use a persistent socket connection or not
58+ */
59+ private $persistentConnection = false;
60+ 61+ /**
62+ * Class constructor
63+ *
64+ * @return void
65+ * @access private
66+ */
67+ private function __construct()
68+ {
69+ 70+ }
71+ 72+ /**
73+ * Singleton pattern. Returns the same instance to all callers
74+ *
75+ * @return Socket
76+ */
77+ public static function singleton()
78+ {
79+ if (self::$instance == null || ! self::$instance instanceof Socket)
80+ {
81+ self::$instance = new Socket();
82+ }
83+ return self::$instance;
84+ }
85+ 86+ /**
87+ * Connects to the socket with the given address and port
88+ *
89+ * @return void
90+ */
91+ public function connect($serverHost=false, $serverPort=false, $timeOut=false)
92+ {
93+ $socketFunction = $this->persistentConnection ? "fsockopen" : "pfsockopen";
94+ 95+ // Check if the function parameters are set.
96+ // If not, use the class defaults
97+ if($serverHost == false)
98+ {
99+ $serverHost = $this->defaultHost;
100+ }
101+ 102+ if($serverPort == false)
103+ {
104+ $serverPort = $this->defaultPort;
105+ }
106+ 107+ if($timeOut == false)
108+ {
109+ $timeOut = $this->defaultTimeout;
110+ }
111+ 112+ $connection = $socketFunction($serverHost, $serverPort, $errorNumber, $errorString, $timeOut);
113+ $this->connection = $connection;
114+ 115+ stream_set_blocking($this->connection, 0);
116+ 117+ if($connection == false)
118+ {
119+ $this->_throwError("Connecting to {$serverHost}:{$serverPort} failed.<br>Reason: {$errorString}");
120+ }
121+ 122+ $this->connectionState = CONNECTED;
123+ }
124+ 125+ /**
126+ * Disconnects from the server
127+ *
128+ * @return True on succes, false if the connection was already closed
129+ */
130+ public function disconnect()
131+ {
132+ if($this->validateConnection())
133+ {
134+ fclose($this->connection);
135+ $this->connectionState = DISCONNECTED;
136+ 137+ return true;
138+ }
139+ 140+ return false;
141+ }
142+ 143+ /**
144+ * Sends a command to the server
145+ *
146+ * @return string Server response
147+ */
148+ public function sendCmd($command)
149+ {
150+ if($this->validateConnection())
151+ {
152+ $command .= "\r\n";
153+ 154+ $result = fwrite($this->connection, $command, strlen($command));
155+ 156+ return $result;
157+ }
158+ 159+ $this->_throwError("Sending command \"{$command}\" failed.<br>Reason: Not connected");
160+ }
161+ 162+ /**
163+ * Gets the server response (not multilined)
164+ *
165+ * @return string Server response
166+ */
167+ public function getResponse()
168+ {
169+ if($this->validateConnection())
170+ {
171+ return fread($this->connection, 2048);
172+ }
173+ 174+ $this->_throwError("Receiving response from server failed.<br>Reason: Not connected");
175+ }
176+ 177+ /**
178+ * Gets a multilined response
179+ *
180+ * @return string Server response
181+ */
182+ public function getMultilinedResponse()
183+ {
184+ $data = '';
185+ while(($tmp = $this->readLine()) != '.')
186+ {
187+ if(substr($tmp, 0, 2) == '..')
188+ {
189+ $tmp = substr($tmp, 1);
190+ }
191+ $data .= $tmp."\r\n";
192+ }
193+ 194+ return substr($data, 0, -2);
195+ }
196+ 197+ /**
198+ * Reads an entire line
199+ *
200+ * @return string Server response
201+ */
202+ public function readLine()
203+ {
204+ $line = '';
205+ while (!feof($this->connection))
206+ {
207+ $line .= fgets($this->connection, 1024);
208+ if (strlen($line) >= 2 && (substr($line, -2) == "\r\n" || substr($line, -1) == "\n"))
209+ {
210+ return rtrim($line);
211+ }
212+ }
213+ return $line;
214+ }
215+ 216+ /**
217+ * Validates the connection state
218+ *
219+ * @return bool
220+ */
221+ private function validateConnection()
222+ {
223+ return (is_resource($this->connection) && ($this->connectionState != DISCONNECTED));
224+ }
225+ 226+ /**
227+ * Throws an error
228+ *
229+ * @return void
230+ */
231+ private function _throwError($errorMessage)
232+ {
233+ throw new Exception("Socket error: " . $errorMessage);
234+ }
235+ 236+ /**
237+ * If there still was a connection alive, disconnect it
238+ */
239+ public function __destruct()
240+ {
241+ $this->disconnect();
242+ }
243+ }
244+ }
245+ 246+ ?>
0 commit comments