socket进行二进制传输学习及测试
首先贴上自测代码server端:
<?php set_time_limit(0); $ip = '127.0.0.1'; $port = 10005; /* +------------------------------- * @socket通信整个过程 +------------------------------- * @socket_create * @socket_bind * @socket_listen * @socket_accept * @socket_read * @socket_write * @socket_close +-------------------------------- */ /*---------------- 以下操作都是手册上的 -------------------*/ if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) { echo "socket_create() 失败的原因是:".socket_strerror($sock)."\n"; } if(($ret = socket_bind($sock,$ip,$port)) < 0) { echo "socket_bind() 失败的原因是:".socket_strerror($ret)."\n"; } if(($ret = socket_listen($sock,4)) < 0) { echo "socket_listen() 失败的原因是:".socket_strerror($ret)."\n"; } $count = 0; do { if (($msgsock = socket_accept($sock)) < 0) { echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n"; break; } else { //发到客户端 $msg ="test success!\n"; socket_write($msgsock, $msg, strlen($msg)); echo "test success \n"; $buf = socket_read($msgsock,8192); // $buf = unpack("c2chars/nint", $buf); $arrSchema = array( "A20username", "A10pwd", "Cage", "Ibirthday", "A50email", ); $buf = unpack(join("/", $arrSchema), $buf); $talkback = "receive message:".json_encode($buf)."\n"; echo $talkback; if(++$count >= 5){ break; }; } //echo $buf; socket_close($msgsock); } while (true); socket_close($sock); ?>
client代码:
<?php error_reporting(E_ALL); set_time_limit(0); // $in = pack("nvc*", 0x1234, 0x5678, 65, 66); // $buf = unpack("c2chars/nint", $in); // var_dump($buf); // exit; echo "TCP/IP Connection\n"; $port = 10005; $ip = "127.0.0.1"; /* * +------------------------------- * @socket连接整个过程 * +------------------------------- * @socket_create * @socket_connect * @socket_write * @socket_read * @socket_close +-------------------------------- */ $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($socket < 0) { echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n"; }else { echo "OK.\n"; } $result = socket_connect($socket, $ip, $port); if ($result < 0) { echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n"; }else { echo "connect OK \n"; } $in = "Ho\n"; $in .= "first blood\n"; // $in = pack("nvc*", 0x1234, 0x5678, 65, 66); /** * 数据格式要求如下: * 用户名:20字节,字符型 * 密码 10字节,字符型 * 年龄 1字节,无符char型 * 出生年月 4字节,整型(19800101) * 邮箱 50字节,字符串 * 各字段间用:"\0"分割 */ $in = ''; $in .= pack('A20',"feiyuhit") ; $in .= pack('A10',"feiyuhit") ; $in .= pack('C',"23") ; $in .= pack('I',"19900101") ; $in .= pack('A50',"feiyuhit@test.com"); $out = ''; if(!socket_write($socket, $in, strlen($in))) { echo "socket_write() failed: reason: " . socket_strerror($socket) . "\n"; }else { echo "send success!\n"; echo "send content :$in"; } while($out = socket_read($socket, 8192)) { echo "request success!\n"; echo "request content:",$out; } echo "close SOCKET\n"; socket_close($socket); echo "close OK\n"; ?>
参考知识点:pack数据格式详解:
字符 说明 a 将字符串空白以 NULL 字符填满 A 将字符串空白以 SPACE 字符 (空格) 填满 h 十六进位字符串,低位在前 H 十六进位字符串,高位在前 c 有号字符 C 无号字符 s 有号短整数 (十六位,依计算机的位顺序) S 无号短整数 (十六位,依计算机的位顺序) n 无号短整数 (十六位, 高位在后的顺序) v 无号短整数 (十六位, 低位在后的顺序) i 有号整数 (依计算机的顺序及范围) I 无号整数 (依计算机的顺序及范围) l 有号长整数 (卅二位,依计算机的位顺序) L 无号长整数 (卅二位,依计算机的位顺序) N 无号短整数 (卅二位, 高位在后的顺序) V 无号短整数 (卅二位, 低位在后的顺序) f 单精确浮点数 (依计算机的范围) d 倍精确浮点数 (依计算机的范围) x 空位 X 倒回一位 @ 填入 NULL 字符到绝对位置
运行结果: