zl程序教程

您现在的位置是:首页 >  后端

当前栏目

php实现与erlang的二进制通讯实例解析

实例PHP二进制 实现 解析 通讯 erlang
2023-06-13 09:15:39 时间

一般来说网络通讯常用的方式有2种:文本通讯和二进制通讯。php与erlang之间实现文本通讯比较简单,这里就不做讨论,本文主要讨论的是php与erlang实现二进制通讯的实现方法。实现步骤如下:

erlang端代码:

复制代码代码如下:

-module(server).
-export([start/0]).

-define(UINT,32/unsigned-little-integer).
-define(INT,32/signed-little-integer).
-define(USHORT,16/unsigned-little-integer).
-define(SHORT,16/signed-little-integer).
-define(UBYTE,8/unsigned-little-integer).
-define(BYTE,8/signed-little-integer).

-define(PORT,5678).

%%启动服务并接受客户端的连接
start()->
 {ok,LSock}=gen_tcp:listen(?PORT,[binary,{packet,0},{active,false}]),
 io:format("socketlisten:~pon~p~n",[LSock,?PORT]),
 accept(LSock).

accept(LSock)->
 {ok,ASock}=gen_tcp:accept(LSock),
 spawn(fun()->server_loop(ASock)end),
 accept(LSock).

server_loop(ASock)->
 casegen_tcp:recv(ASock,0)of
   {ok,<<Len:?USHORT,Cmd:?USHORT,Contain:4/binary-unit:8>>=A}->
     io:format("recvdata:~p~p~p~n",[Len,Cmd,Contain]),
     %%将接收到数据发送回客户端
     gen_tcp:send(ASock,A),
     server_loop(ASock);
   {ok,Data}->
     io:format("recvunformateddata:~p~n",[Data]),
     server_loop(ASock);
   {error,_}->
     {ok,recv_error}
   end.

php端代码:

<?php

$timeout=3;
//超时时间:3秒

$fp=fsockopen("tcp://127.0.0.1",5678,$errno,$errstr,$timeout/*连接超时时间*/);
if(!$fp){
echo"$errstr($errno)<br/>\n";
}else{
stream_set_timeout($fp,$timeout);
//远程数据接收或发送超时时间

$format="vva4";
$data=pack($format,4,10001,"abcd");
//$data按照一定格式被打包成二进制数据

fwrite($fp,$data);

if(!feof($fp)){

$rs=fread($fp,1024);
//读取远程数据
if($rs){

$len=strlen($rs);
//$len可以获取数据的长度,用以计算content的长度
//在这个例子中,content的长度为4

$format="vlen/vcmd/a4content";
$data=unpack($format,$rs);

print_r($data);
}else{
echo"timeout!";
}
}else{
echo"timeout!";
}
fclose($fp);
}
?>

运行正常的情况下,php端会显示以下内容:

Array([len]=>4[cmd]=>10001[content]=>abcd)

针对通讯的一些说明

这里用到的是php的pack函数和unpack函数:

pack函数:将数据按照一定格式打包成二进制数据,生成的数据接近C/C++的结构体数据(C/C++字符串带结束符)。

unpack函数:与pack相反,对二进制数据进行解包。

对应的erlang端,则直接用位语法来匹配二进制数据即可。