server.php
<?php
class TestTCPServer
{
public $sock = NULL;
public function __construct($addr = "127.0.0.1", $port = 5000)
{
$sock = $this->newSocket($addr, $port);
$this->sock = $sock;
}
public function newSocket($addr, $port)
{
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
throw new \Exception("socket_create() failed: ".socket_strerror(socket_last_error()));
}
if ((socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) === false) {
throw new \Exception("socket_set_option() failed: ".socket_strerror(socket_last_error()));
}
if ((socket_bind($sock, $addr, $port)) === false) {
throw new \Exception("socket_bind() failed: ".socket_strerror(socket_last_error($sock)));
}
if (socket_listen($sock) === false) {
throw new \Exception("socket_listen() failed: ".socket_strerror(socket_last_error($sock)));
}
return $sock;
}
public function run(Closure $code)
{
while ($remote = socket_accept($this->sock)) {
while ($line = socket_read($remote, 1024)) {
$code($remote, $line, $this->sock);
}
}
}
}
データを受信した後の処理は、コールバックで書くようにしている。
echoサーバを書く場合は、以下のようになる。
echo_server.php
<?php
require_once 'server.php';
$server = new TestTCPServer();
$server->run(function($remote, $line, $sock) {
socket_write($remote, $line);
});
実行するとブロックするので、
バックグランドで実行しつつ、以下のように動作確認できる。
$ telnet 127.0.0.1 5000
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
test message
test message
クライアント側もPHPで書くとしたら、以下のようになる。
echo_client.php
<?php
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
die("socket_create() failed: ".socket_strerror(socket_last_error()));
}
if (socket_connect($sock, '127.0.0.1', 5000) === false) {
die("socket_connect() failed: ".socket_strerror(socket_last_error()));
}
$buf = "foo\n";
socket_write($sock, $buf, strlen($buf));
echo socket_read($sock, strlen($buf));
$buf = "bar\n";
socket_write($sock, $buf, strlen($buf));
echo socket_read($sock, strlen($buf));
socket_close($sock);
参考