所以,client 端傳送的資料為 => 4 bytes 的數字(資料本體長度) + 資料本體
同樣,client 端接收到資料為 => 4 bytes 的數字(資料本體長度) + 資料本體
//client 傳送:前4個bytes為要傳送的資料本體長度,後面緊接著資料本體 //server 回應:前4個bytes為回應的資料本體長度,後面緊接著資料本體 $data = "這是要傳送的資料本體"; //socket $url = "http://example.com:8888"; $url_part = parse_url($url); $host = $url_part["host"]; $address = gethostbyname($host); $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!$socket) { $err_msg = socket_strerror(socket_last_error($socket)); socket_close($socket); throw new Exception("socket_create() failed:" . $err_msg); } $conn = socket_connect($socket, $address, $api_def->getSocketPort()); if (!$conn) { $err_msg = socket_strerror(socket_last_error($socket)); socket_close($socket); throw new Exception("socket_connect() failed:" . $err_msg); } //傳送資料 $bin_body = pack("a*", $data); //$bin_body = $data; $body_len = strlen($bin_body); $bin_head = pack("N", $body_len); //unsigned long (always 32 bit, big endian byte order)=>數字轉成一個 4 bytes 的big endian byte order $bin_data = $bin_head . $bin_body; //4bytes資料本體長度 + 資料本體 $res = socket_write($socket, $bin_data, strlen($bin_data)); //返回成功寫入的bytes數 or false if (!$res) { $err_msg = socket_strerror(socket_last_error($socket)); socket_close($socket); throw new Exception("socket_write() failed:" . $err_msg); } //接收資料 $buf = ""; //先取得 4bytes 回應資料本體長度 if (false === ($bytes = socket_recv($socket, $buf, 4, MSG_WAITALL))) { //返回接收到的長度 or false。MSG_WAITALL:阻塞模式,若過程沒異常,一直等到讀到指定長度 $err_msg = socket_strerror(socket_last_error($socket)); socket_close($socket); throw new Exception("讀取資料長度失敗 socket_recv() failed:" . $err_msg); } $len_data = unpack("Nlen", $buf); //N:unsigned long (always 32 bit, big endian byte order)=>解析頭 4 個bytes //再用取得的資料本體長度,抓回應資料本體 if (false === ($bytes = socket_recv($socket, $buf, $len_data["len"], MSG_WAITALL))) { //返回接收到的長度 or false。MSG_WAITALL:阻塞模式,若過程沒異常,一直等到讀到指定長度 $err_msg = socket_strerror(socket_last_error($socket)); socket_close($socket); throw new Exception("讀取回應資料本體失敗 socket_recv() failed:" . $err_msg); } socket_close($socket); var_dump($buf);//回應的資料本體
參考:
PHP: 深入pack/unpack - 陈亦的个人页面 - 开源中国社区
[转帖]pack/unpack用法----心得筆記 - Perl Forum
PHP: pack - Manual
PHP: socket_recv - Manual
bytearray - String to byte array in php - Stack Overflow
java的int和byte數組的相互轉換_我們關註網
IO模式设置网络编程常见问题总结—IO模式设置,阻塞与非阻塞的比较,recv参数对性能的影响—O_NONBLOCK(open使用)、IPC_NOWAIT(msgrcv)、MSG_DONTWAIT(re - houlaizhe221的专栏 - 博客频道 - CSDN.NET
沒有留言:
張貼留言