summaryrefslogtreecommitdiff
path: root/localwebsite/classes/MySimpleSocketClient.php
blob: e59efbad48b52d7779b52e9d25028242a60c7aa3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php

class MySimpleSocketClient {

    protected $sock;

    public function __construct(string $host, int $port)
    {
        if (($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false)
            throw new Exception("socket_create() failed: ".$this->getSocketError());
        
        $this->sock = $socket;

        if ((socket_connect($socket, $host, $port)) === false)
            throw new Exception("socket_connect() failed: ".$this->getSocketError());
    }

    public function __destruct()
    {
        $this->close();
    }

    /**
     * @throws Exception
     */
    public function send(string $data)
    {
        $data .= "\r\n";
        $remained = strlen($data);

        while ($remained > 0) {
            $result = socket_write($this->sock, $data);
            if ($result === false)
                throw new Exception(__METHOD__ . ": socket_write() failed: ".$this->getSocketError());

            $remained -= $result;
            if ($remained > 0)
                $data = substr($data, $result);
        }
    }

    /**
     * @throws Exception
     */
    public function recv()
    {
        $recv_buf = '';
        $buf = '';

        while (true) {
            $result = socket_recv($this->sock, $recv_buf, 1024, 0);
            if ($result === false)
                throw new Exception(__METHOD__ . ": socket_recv() failed: " . $this->getSocketError());

            // peer disconnected
            if ($result === 0)
                break;

            $buf .= $recv_buf;
            if (endsWith($buf, "\r\n"))
                break;
        }

        return trim($buf);
    }

    /**
     * Close connection.
     */
    public function close()
    {
        if (!$this->sock)
            return;

        socket_close($this->sock);
        $this->sock = null;
    }

    /**
     * @return string
     */
    protected function getSocketError(): string
    {
        $sle_args = [];
        if ($this->sock !== null)
            $sle_args[] = $this->sock;
        return socket_strerror(socket_last_error(...$sle_args));
    }

}