Skip to content

Commit eabd5ba

Browse files
committed
Refactor sockets extension to use new TrueAsync API
- Update network_async_wait_socket() to use modern async API with waker pattern - Replace async_wait_socket() calls with network_async_wait_socket() in all socket functions - Affected PHP functions: socket_read, socket_send, socket_recv, socket_sendto, socket_recvfrom, socket_connect, socket_accept - Add comprehensive test suite in ext/async/tests/socket_ext/ covering TCP/UDP operations and concurrent scenarios
1 parent 3db142e commit eabd5ba

7 files changed

+543
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
--TEST--
2+
socket_read() async operation
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('sockets')) {
6+
die('skip sockets extension not available');
7+
}
8+
?>
9+
--FILE--
10+
<?php
11+
12+
use function Async\spawn;
13+
use function Async\awaitAll;
14+
use function Async\delay;
15+
16+
echo "Start\n";
17+
18+
// Shared variable for server port
19+
$port = null;
20+
21+
// Server coroutine
22+
$server = spawn(function() use (&$port) {
23+
echo "Server: creating socket\n";
24+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
25+
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
26+
socket_bind($socket, '127.0.0.1', 0);
27+
socket_listen($socket);
28+
29+
$addr = '';
30+
socket_getsockname($socket, $addr, $port);
31+
echo "Server: listening on port $port\n";
32+
33+
echo "Server: waiting for connection\n";
34+
$client = socket_accept($socket);
35+
echo "Server: client connected\n";
36+
37+
$data = socket_read($client, 1024);
38+
echo "Server: received '$data'\n";
39+
40+
socket_write($client, "Hello from server");
41+
echo "Server: response sent\n";
42+
43+
socket_close($client);
44+
socket_close($socket);
45+
});
46+
47+
// Client coroutine
48+
$client = spawn(function() use (&$port) {
49+
// Wait for the server to set the port
50+
while ($port === null) {
51+
delay(1);
52+
}
53+
54+
echo "Client: connecting\n";
55+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
56+
if (!socket_connect($socket, '127.0.0.1', $port)) {
57+
echo "Client: failed to connect\n";
58+
return;
59+
}
60+
61+
socket_write($socket, "Hello from client");
62+
echo "Client: sent request\n";
63+
64+
$response = socket_read($socket, 1024);
65+
echo "Client: received '$response'\n";
66+
67+
socket_close($socket);
68+
});
69+
70+
// Worker coroutine for parallel execution
71+
$worker = spawn(function() {
72+
echo "Worker: doing work while server waits\n";
73+
});
74+
75+
awaitAll([$server, $client, $worker]);
76+
echo "End\n";
77+
78+
?>
79+
--EXPECTF--
80+
Start
81+
Server: creating socket
82+
Worker: doing work while server waits
83+
Server: listening on port %d
84+
Server: waiting for connection
85+
Client: connecting
86+
Server: client connected
87+
Client: sent request
88+
Server: received 'Hello from client'
89+
Server: response sent
90+
Client: received 'Hello from server'
91+
End
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
--TEST--
2+
socket_recv() and socket_send() async operations
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('sockets')) {
6+
die('skip sockets extension not available');
7+
}
8+
?>
9+
--FILE--
10+
<?php
11+
12+
use function Async\spawn;
13+
use function Async\awaitAll;
14+
use function Async\delay;
15+
16+
echo "Start\n";
17+
18+
$port = null;
19+
20+
// Server coroutine
21+
$server = spawn(function() use (&$port) {
22+
echo "Server: creating socket\n";
23+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
24+
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
25+
socket_bind($socket, '127.0.0.1', 0);
26+
socket_listen($socket);
27+
28+
$addr = '';
29+
socket_getsockname($socket, $addr, $port);
30+
echo "Server: listening on port $port\n";
31+
32+
$client = socket_accept($socket);
33+
echo "Server: client connected\n";
34+
35+
$buffer = '';
36+
$bytes = socket_recv($client, $buffer, 1024, MSG_WAITALL);
37+
echo "Server: received $bytes bytes: '$buffer'\n";
38+
39+
$sent = socket_send($client, "Response from server", 20, 0);
40+
echo "Server: sent $sent bytes\n";
41+
42+
socket_close($client);
43+
socket_close($socket);
44+
});
45+
46+
// Client coroutine
47+
$client = spawn(function() use (&$port) {
48+
while ($port === null) {
49+
delay(1);
50+
}
51+
52+
echo "Client: connecting\n";
53+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
54+
socket_connect($socket, '127.0.0.1', $port);
55+
56+
$sent = socket_send($socket, "Request from client", 19, 0);
57+
echo "Client: sent $sent bytes\n";
58+
59+
$buffer = '';
60+
$bytes = socket_recv($socket, $buffer, 1024, MSG_WAITALL);
61+
echo "Client: received $bytes bytes: '$buffer'\n";
62+
63+
socket_close($socket);
64+
});
65+
66+
awaitAll([$server, $client]);
67+
echo "End\n";
68+
69+
?>
70+
--EXPECTF--
71+
Start
72+
Server: creating socket
73+
Server: listening on port %d
74+
Client: connecting
75+
Server: client connected
76+
Client: sent 19 bytes
77+
Server: received 19 bytes: 'Request from client'
78+
Server: sent 20 bytes
79+
Client: received 20 bytes: 'Response from server'
80+
End
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
--TEST--
2+
socket_sendto() and socket_recvfrom() async operations with UDP
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('sockets')) {
6+
die('skip sockets extension not available');
7+
}
8+
?>
9+
--FILE--
10+
<?php
11+
12+
use function Async\spawn;
13+
use function Async\awaitAll;
14+
use function Async\delay;
15+
16+
echo "Start\n";
17+
18+
$port = null;
19+
20+
// Server coroutine (UDP)
21+
$server = spawn(function() use (&$port) {
22+
echo "Server: creating UDP socket\n";
23+
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
24+
socket_bind($socket, '127.0.0.1', 0);
25+
26+
$addr = '';
27+
socket_getsockname($socket, $addr, $port);
28+
echo "Server: listening on UDP port $port\n";
29+
30+
$buffer = '';
31+
$from = '';
32+
$from_port = 0;
33+
$bytes = socket_recvfrom($socket, $buffer, 1024, 0, $from, $from_port);
34+
echo "Server: received $bytes bytes from $from:$from_port: '$buffer'\n";
35+
36+
$sent = socket_sendto($socket, "UDP response", 12, 0, $from, $from_port);
37+
echo "Server: sent $sent bytes back to client\n";
38+
39+
socket_close($socket);
40+
});
41+
42+
// Client coroutine (UDP)
43+
$client = spawn(function() use (&$port) {
44+
while ($port === null) {
45+
delay(1);
46+
}
47+
48+
echo "Client: creating UDP socket\n";
49+
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
50+
51+
$sent = socket_sendto($socket, "UDP request", 11, 0, '127.0.0.1', $port);
52+
echo "Client: sent $sent bytes\n";
53+
54+
$buffer = '';
55+
$from = '';
56+
$from_port = 0;
57+
$bytes = socket_recvfrom($socket, $buffer, 1024, 0, $from, $from_port);
58+
echo "Client: received $bytes bytes from $from:$from_port: '$buffer'\n";
59+
60+
socket_close($socket);
61+
});
62+
63+
awaitAll([$server, $client]);
64+
echo "End\n";
65+
66+
?>
67+
--EXPECTF--
68+
Start
69+
Server: creating UDP socket
70+
Server: listening on UDP port %d
71+
Client: creating UDP socket
72+
Client: sent 11 bytes
73+
Server: received 11 bytes from 127.0.0.1:%d: 'UDP request'
74+
Server: sent 12 bytes back to client
75+
Client: received 12 bytes from 127.0.0.1:%d: 'UDP response'
76+
End
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
--TEST--
2+
socket_connect() async operation
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('sockets')) {
6+
die('skip sockets extension not available');
7+
}
8+
?>
9+
--FILE--
10+
<?php
11+
12+
use function Async\spawn;
13+
use function Async\awaitAll;
14+
use function Async\delay;
15+
16+
echo "Start\n";
17+
18+
$port = null;
19+
20+
// Server coroutine
21+
$server = spawn(function() use (&$port) {
22+
echo "Server: creating socket\n";
23+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
24+
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
25+
socket_bind($socket, '127.0.0.1', 0);
26+
socket_listen($socket);
27+
28+
$addr = '';
29+
socket_getsockname($socket, $addr, $port);
30+
echo "Server: listening on port $port\n";
31+
32+
echo "Server: accepting connections\n";
33+
$client1 = socket_accept($socket);
34+
echo "Server: client1 connected\n";
35+
36+
$client2 = socket_accept($socket);
37+
echo "Server: client2 connected\n";
38+
39+
socket_write($client1, "Hello client1");
40+
socket_write($client2, "Hello client2");
41+
42+
socket_close($client1);
43+
socket_close($client2);
44+
socket_close($socket);
45+
});
46+
47+
// Client coroutines
48+
$client1 = spawn(function() use (&$port) {
49+
while ($port === null) {
50+
delay(1);
51+
}
52+
53+
echo "Client1: connecting\n";
54+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
55+
56+
if (socket_connect($socket, '127.0.0.1', $port)) {
57+
echo "Client1: connected successfully\n";
58+
$data = socket_read($socket, 1024);
59+
echo "Client1: received '$data'\n";
60+
} else {
61+
echo "Client1: connection failed\n";
62+
}
63+
64+
socket_close($socket);
65+
});
66+
67+
$client2 = spawn(function() use (&$port) {
68+
while ($port === null) {
69+
delay(1);
70+
}
71+
72+
echo "Client2: connecting\n";
73+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
74+
75+
if (socket_connect($socket, '127.0.0.1', $port)) {
76+
echo "Client2: connected successfully\n";
77+
$data = socket_read($socket, 1024);
78+
echo "Client2: received '$data'\n";
79+
} else {
80+
echo "Client2: connection failed\n";
81+
}
82+
83+
socket_close($socket);
84+
});
85+
86+
awaitAll([$server, $client1, $client2]);
87+
echo "End\n";
88+
89+
?>
90+
--EXPECTF--
91+
Start
92+
Server: creating socket
93+
Server: listening on port %d
94+
Server: accepting connections
95+
Client1: connecting
96+
Client1: connected successfully
97+
Server: client1 connected
98+
Client2: connecting
99+
Client2: connected successfully
100+
Server: client2 connected
101+
Client1: received 'Hello client1'
102+
Client2: received 'Hello client2'
103+
End

0 commit comments

Comments
 (0)