erlang 连接php-fpm

本文分享了一个使用Erlang连接PHP-FPM的示例代码,并修复了两个bug:一是处理超过128字符的参数问题;二是解决PHP响应超过1024字节时的错误。通过示例代码,展示了如何在Erlang中进行TCP连接并发送FCGI请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前端时间在网上看见erlang 连接php-fpm的例子,自己跟到弄了一下,下面给我调试后的代码贴出来

我修正了原来代码的2处bug:

1、参数超过128字符出错

2、当php返回超过1024字节时候出错

文件名fastcgi.erl

-module(fastcgi).
-compile(export_all).


do_request(Argv)
->
Env
= [
{
"SCRIPT_FILENAME","E:/phpGame/game/gateway.php"},
{
"websocket",Argv}
],
io:format(
"Argv msg: ~ts~n", [Argv]),
{ok, Socket}
=gen_tcp:connect("127.0.0.1",9000,[binary, {packet, 0}, {active,true}],10000),
fcgi_send_record(Socket,
1,1,<<1:16,0:8,0:40>>),
fcgi_send_record(Socket,
4,1, Env),
fcgi_send_record(Socket,
4,1, []),
Bin
= phpRespone(Socket,[]),
gen_tcp:close(Socket),
%%原报文<<Version:8, Type:8, RequestId:16, ContentLength:16,PaddingLength:8, Reserved:8,Str/binary >> = Bin,
<<_:32,ContentLength:16,_:16,Str/binary >> = Bin,
%%计算输出内容长度
Dlen
=ContentLength-52,
%%获取内容
<< _H:52/binary,Data:Dlen/binary,_Other/binary >> = Str,
io:fwrite(
"rs:~p~n",[Data]),
{ok,Data}.


recv_msg(Sock)
->
receive
{tcp, Sock, Bin}
->
io:format(
"Bin msg: ~p~n", [Bin]),
%%原报文<<Version:8, Type:8, RequestId:16, ContentLength:16,PaddingLength:8, Reserved:8,Str/binary >> = Bin,
<<_:32,ContentLength:16,_:16,Str/binary >> = Bin,
%%计算输出内容长度
Dlen
=ContentLength-52,
%%获取内容
<< _H:52/binary,Data:Dlen/binary,_Other/binary >> = Str,
io:fwrite(
"rs:~p~n",[Data]),
{ok,Data};
{tcp_closed,Sock}
->
io:format(
"socket close: ~p~n", [Sock]);
_Other
->
io:format(
"Other msg: ~p~n", [_Other]),
recv_msg(Sock)
after
3000 ->io:format("Time out.~n")
end.

phpRespone(Sock,SoFar)
->
receive
{tcp, Sock, Bin}
->
phpRespone(Sock,[Bin
|SoFar]);
{tcp_closed,Sock}
->
list_to_binary(lists:reverse(SoFar));
_Other
->
io:format(
"Other msg: ~p~n", [_Other]),
phpRespone(Sock,SoFar)
after
3000 ->io:format("Time out.~n")
end.


%%发送选项
fcgi_send_record(Socket, Type, RequestId, NameValueList)
->
EncodedRecord
= fcgi_encode_record(Type, RequestId,NameValueList),
gen_tcp:send(Socket, EncodedRecord).



%%组包
fcgi_encode_record(Type, RequestId, NameValueList) when is_list(NameValueList)
->
fcgi_encode_record(Type, RequestId,fcgi_encode_name_value_list(NameValueList));

%%判断ContentData是否满8字节,否则填充
fcgi_encode_record(Type, RequestId, ContentData) when is_binary(ContentData)
->
ContentLength
= size(ContentData),
PaddingLength
= if
ContentLength rem
8 == 0 ->
0;
true
->
8 - (ContentLength rem 8)
end,
%%填充数据,每8字节组包 不足用0填充
PaddingData
= <<0:(PaddingLength*8)>>,
Version
= 1,
Reserved
= 0,
<<Version:8,
Type:
8,
RequestId:
16,
ContentLength:
16,
PaddingLength:
8,
Reserved:
8,
ContentData
/binary,
PaddingData
/binary >>.

%%将环境变量组成binary
fcgi_encode_name_value_list(_NameValueList
= []) ->
<< >>;

fcgi_encode_name_value_list(_NameValueList
= [{Name, Value} | Tail]) ->
<<(fcgi_encode_name_value(Name,Value))/binary,(fcgi_encode_name_value_list(Tail))/binary >>.

fcgi_encode_name_value(Name, _Value
= undefined) ->
fcgi_encode_name_value(Name,
"");

fcgi_encode_name_value(Name, Value) when is_list(Name)
and is_list(Value) ->
NameSize
= length(Name),
NameSizeData
= << NameSize:8>>,
ValueSize
= length(Value),

if ValueSize < 128 ->
ValueSizeData
= <<ValueSize:8>>;
ValueSize
> 127 ->
ValueSizeData
= <<(ValueSize bor 16#80000000):32>>
end,

<< NameSizeData/binary,ValueSizeData/binary,(list_to_binary(Name))/binary,(list_to_binary(Value))/binary >>.

在windows 下启动php cgi可以这样做

php-cgi.exe -b 127.0.0.1:9000

在erlang shell中调用:

2> c(fastcgi).
{ok,fastcgi}
3> fastcgi:do_request("{'uid':1}").

文笔不好,请大家多多包含

转载于:https://www.cnblogs.com/wufoxfm95/archive/2011/04/18/2020007.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值