70 lines
2.0 KiB
PHP
70 lines
2.0 KiB
PHP
<?php
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\Log;
|
|
use Exception;
|
|
|
|
class TcpSocketClient
|
|
{
|
|
protected string $ip;
|
|
protected int $port;
|
|
protected int $timeout;
|
|
|
|
public function __construct(string $ip, int $port, int $timeout = 5)
|
|
{
|
|
$this->ip = $ip;
|
|
$this->port = $port;
|
|
$this->timeout = $timeout;
|
|
}
|
|
|
|
public function send(string $data, string $breakOn = "\n"): string
|
|
{
|
|
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
|
if ($socket === false) {
|
|
$err = socket_strerror(socket_last_error());
|
|
Log::error("Socket create failed: {$err}");
|
|
throw new Exception("Socket create failed: {$err}");
|
|
}
|
|
|
|
// 設定寫入超時(發送)
|
|
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, [
|
|
'sec' => $this->timeout,
|
|
'usec' => 0,
|
|
]);
|
|
// 設定讀取超時(接收)
|
|
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, [
|
|
'sec' => $this->timeout,
|
|
'usec' => 0,
|
|
]);
|
|
|
|
$result = socket_connect($socket, $this->ip, $this->port);
|
|
if ($result === false) {
|
|
$err = socket_strerror(socket_last_error($socket));
|
|
Log::error("Socket connect failed: {$err}");
|
|
throw new Exception("Socket connect failed: {$err}");
|
|
}
|
|
|
|
$write = socket_write($socket, $data, strlen($data));
|
|
if ($write === false) {
|
|
$err = socket_strerror(socket_last_error($socket));
|
|
Log::error("Socket write failed: {$err}");
|
|
throw new Exception("Socket write failed: {$err}");
|
|
}
|
|
|
|
$response = '';
|
|
while ($out = socket_read($socket, 2048)) {
|
|
$response .= $out;
|
|
if ($breakOn && strpos($response, $breakOn) !== false) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
socket_close($socket);
|
|
|
|
if ($response === '') {
|
|
Log::warning('Socket read empty or timeout.');
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
} |