工業控制、儀器儀表、舊版通訊協定常要求以十六進位位元組串流收發資料(如 Modbus TCP、自訂協定)。PHP Socket 操作需將十六進位字串轉為二進位位元組發送,接收後再轉回十六進位解析。
<?php
// 1. 要發送的十六進位資料(空格分隔方便閱讀)
$hexString = '30 32 30 34 03 30 33'; // 對應 ASCII "0204\x0303"
// 2. 轉換為位元組陣列:移除空格 → 每兩字元一組 → hexdec → chr
$bytes = array_map('chr', array_map('hexdec', str_split(str_replace(' ', '', $hexString), 2)));
// 3. 建立 TCP Socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die('socket_create 失敗:' . socket_strerror(socket_last_error()));
}
// 4. 連線目標伺服器
$host = '192.168.1.100';
$port = 8080;
if (!socket_connect($socket, $host, $port)) {
die('socket_connect 失敗:' . socket_strerror(socket_last_error($socket)));
}
// 5. 發送資料(逐位元組寫入)
foreach ($bytes as $byte) {
socket_write($socket, $byte, 1);
}
// 6. 接收回應(二進位模式)
$response = socket_read($socket, 1024, PHP_BINARY_READ);
if ($response === false) {
die('socket_read 失敗:' . socket_strerror(socket_last_error($socket)));
}
// 7. 將二進位回應轉為十六進位顯示
$responseHex = bin2hex($response);
echo "Server response (hex): $responseHex\n";
// 8. 關閉連線
socket_close($socket);
?>
| 函式 | 用途 | 關鍵參數 |
|---|---|---|
socket_create | 建立 Socket 資源 | AF_INET (IPv4), SOCK_STREAM (TCP), SOL_TCP |
socket_connect | 連線遠端 | IP, Port |
socket_write | 發送資料 | 資料, 長度 |
socket_read | 讀取資料 | 長度, PHP_BINARY_READ (二進位) / PHP_NORMAL_READ (換行結束) |
bin2hex | 二進位 → 十六進位字串 | — |
hex2bin | 十六進位字串 → 二進位 (PHP 5.4+) | — |
chr(hexdec($hex)) | 單位元組十六進位 → 字元 | — |
<?php
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($server, '0.0.0.0', 8080);
socket_listen($server);
echo "Server listening on 8080...\n";
while (true) {
$client = socket_accept($server);
$input = socket_read($client, 1024, PHP_BINARY_READ);
echo "Received: " . bin2hex($input) . "\n";
// 簡單回應:原樣返回
socket_write($client, $input);
socket_close($client);
}
?>
CAP_NET_BIND_SERVICE 才能綁定 < 1024 埠。socket_read 會等待資料。非阻塞需 socket_set_nonblock() 配合 socket_select()。