Skip to content

Commit 01ef499

Browse files
committed
Split connection processing part of loop out
This is so that implementors can subclass the server to do things other than just handle websockets. For example, you might want a GameServer that processes server-side events at regular ticks. This is hard to do if the entire main loop of the server is in a single scope: you'd have to override the entire run() method. This commit simply moves the contents of the inside of the main loop in run() into a separate method (processSockets()). It's understood this method might take upwards of five seconds to return.
1 parent cfb7c71 commit 01ef499

File tree

1 file changed

+69
-57
lines changed

1 file changed

+69
-57
lines changed

server/lib/WebSocket/Server.php

+69-57
Original file line numberDiff line numberDiff line change
@@ -39,80 +39,92 @@ protected function createConnection($resource)
3939
}
4040

4141
/**
42-
* Main server method. Listens for connections, handles connectes/disconnectes, e.g.
42+
* Main server loop
43+
*
44+
* This method does not return.
4345
*/
4446
public function run()
4547
{
46-
while(true)
48+
while(true) {
49+
$this->processSockets();
50+
}
51+
}
52+
53+
/**
54+
* Selects all active sockets for read events, and processes those whose
55+
* state changes. Listens for connections, handles connects/disconnects, e.g.
56+
*
57+
* @return void
58+
*/
59+
protected function processSockets()
60+
{
61+
$changed_sockets = $this->allsockets;
62+
@stream_select($changed_sockets, $write = null, $except = null, 0, 5000);
63+
foreach($changed_sockets as $socket)
4764
{
48-
$changed_sockets = $this->allsockets;
49-
@stream_select($changed_sockets, $write = null, $except = null, 0, 5000);
50-
foreach($changed_sockets as $socket)
65+
if($socket == $this->master)
5166
{
52-
if($socket == $this->master)
67+
if(($resource = stream_socket_accept($this->master)) === false)
5368
{
54-
if(($resource = stream_socket_accept($this->master)) === false)
55-
{
56-
$this->log('Socket error: ' . socket_strerror(socket_last_error($resource)));
57-
continue;
58-
}
59-
else
60-
{
61-
$client = $this->createConnection($resource);
62-
$this->clients[(int)$resource] = $client;
63-
$this->allsockets[] = $resource;
64-
65-
if(count($this->clients) > $this->_maxClients)
66-
{
67-
$client->onDisconnect();
68-
if($this->getApplication('status') !== false)
69-
{
70-
$this->getApplication('status')->statusMsg('Attention: Client Limit Reached!', 'warning');
71-
}
72-
continue;
73-
}
74-
75-
$this->_addIpToStorage($client->getClientIp());
76-
if($this->_checkMaxConnectionsPerIp($client->getClientIp()) === false)
77-
{
78-
$client->onDisconnect();
79-
if($this->getApplication('status') !== false)
80-
{
81-
$this->getApplication('status')->statusMsg('Connection/Ip limit for ip ' . $client->getClientIp() . ' was reached!', 'warning');
82-
}
83-
continue;
84-
}
85-
}
69+
$this->log('Socket error: ' . socket_strerror(socket_last_error($resource)));
70+
continue;
8671
}
8772
else
8873
{
89-
$client = $this->clients[(int)$socket];
90-
if(!is_object($client))
91-
{
92-
unset($this->clients[(int)$socket]);
93-
continue;
94-
}
95-
$data = $this->readBuffer($socket);
96-
$bytes = strlen($data);
74+
$client = $this->createConnection($resource);
75+
$this->clients[(int)$resource] = $client;
76+
$this->allsockets[] = $resource;
9777

98-
if($bytes === 0)
78+
if(count($this->clients) > $this->_maxClients)
9979
{
10080
$client->onDisconnect();
81+
if($this->getApplication('status') !== false)
82+
{
83+
$this->getApplication('status')->statusMsg('Attention: Client Limit Reached!', 'warning');
84+
}
10185
continue;
10286
}
103-
elseif($data === false)
104-
{
105-
$this->removeClientOnError($client);
106-
continue;
107-
}
108-
elseif($client->waitingForData === false && $this->_checkRequestLimit($client->getClientId()) === false)
87+
88+
$this->_addIpToStorage($client->getClientIp());
89+
if($this->_checkMaxConnectionsPerIp($client->getClientIp()) === false)
10990
{
11091
$client->onDisconnect();
92+
if($this->getApplication('status') !== false)
93+
{
94+
$this->getApplication('status')->statusMsg('Connection/Ip limit for ip ' . $client->getClientIp() . ' was reached!', 'warning');
95+
}
96+
continue;
11197
}
112-
else
113-
{
114-
$client->onData($data);
115-
}
98+
}
99+
}
100+
else
101+
{
102+
$client = $this->clients[(int)$socket];
103+
if(!is_object($client))
104+
{
105+
unset($this->clients[(int)$socket]);
106+
continue;
107+
}
108+
$data = $this->readBuffer($socket);
109+
$bytes = strlen($data);
110+
111+
if($bytes === 0)
112+
{
113+
$client->onDisconnect();
114+
continue;
115+
}
116+
elseif($data === false)
117+
{
118+
$this->removeClientOnError($client);
119+
continue;
120+
}
121+
elseif($client->waitingForData === false && $this->_checkRequestLimit($client->getClientId()) === false)
122+
{
123+
$client->onDisconnect();
124+
}
125+
else
126+
{
127+
$client->onData($data);
116128
}
117129
}
118130
}

0 commit comments

Comments
 (0)