读书人

[dika 记要] cowboy 扩展socket 协议

发布时间: 2012-08-13 13:21:53 作者: rapoo

[dika 记录] cowboy 扩展socket 协议, 以解决flash ,erlang通讯的沙箱为例子


cowboy 的 acceptor pool是通用的,而且说实话,acceptor pool的写法都那样,学习是可以的,但是没必要重复造轮子了.


记录一下 直接使用cowboy做底层socket设施:

把cowboy的依赖打上,我是用rebar的,deps上加上cowboy的git, 可以直接下载源码,放到自己项目中.


要使用很简单,启动cowboy listener 并指定 要回调的协议处理模块.

我就分了两个文件,dp_socket_service.erl dp_proto_handler.erl .

开始先介绍比较通用部分的写法,后面再加入flash沙箱策略文件的socket例子


dp_socket_service.erl 使用了gen_server ,目的只是启动了,cowboy listener


这里没有什么特别,下面开始写协议处理模块.


init([]) ->
cowboy:start_listener(dp_listener, 100,
cowboy_tcp_transport, [{port,88}],
dp_proto_handler,[]
).

cowboy 有定义了behaviour

-module(cowboy_protocol).

-export([behaviour_info/1]).

%% @private
-spec behaviour_info(_)->undefined | [{start_link, 4}, ...].
behaviour_info(callbacks) ->
[{start_link, 4}];
behaviour_info(_Other) ->
undefined.



可见,要暴露的start_link/4的接口即可, 而四个参数是什么? 最简单办法就是打开cowboy_http_protocol.erl看看


%% @doc Start an HTTP protocol process.
-spec start_link(pid(), inet:socket(), module(), any()) ->{ok, pid()}.

start_link(ListenerPid, Socket, Transport, Opts) ->

这样很清晰了.可以动手了

dp_proto_handler.erl

-spec start_link(pid(), ssl:sslsocket(), module(), []) ->;{ok, pid()}.
start_link(_ListenerPid, Socket, Transport, []) ->;
Pid = spawn_link(?MODULE, init, [Socket, Transport]),
{ok, Pid}.


init(Socket, Transport) ->
recv(#state{socket=Socket, transport=Transport}),
ok.

把一些我不需要的参数忽略了.开了个进程来处理

recv就是负责处理包的,下面写法有两种了.

一,调用Transport的方法,其实就是调用gen_tcp

二,用receive 原语

-------------------------------------------------以flash 沙箱策略文件为例子--------------------

先定义了这次的请求把,

-define(FLASH_REQ, <<"<policy-file-request/>\0">>). %%这里记得是后面 \0补全阿
-define(FLASH_FILE, <<"<cross-domain-policy><allow-access-from domain='*' to-ports='*' /></cross-domain-policy>">>).



第一种,直接调用Transport的方法收包发包.

recv(#state{socket=Socket, transport=Transport})->
case Transport:recv(Socket, 0, 5000) of
{ok, ?FLASH_REQ}->Transport:send(Socket,?FLASH_FILE),terminate();
{ok,Other}-> ok;
{error, _Reason} -> terminate()
end.


第二种,receive原句

recv(#state{socket=Socket, transport=Transport})->

Transport:setopts(Socket, [{active, once}]),

receive

{ok, ?FLASH_REQ}->Transport:send(Socket,?FLASH_FILE),terminate();
{ok,Other}-> ok;
{error, _Reason} -> terminate()
end.



总结,用法跟直接用tcp都差不多.


by dp~~


读书人网 >Flash

热点推荐