主要是利用rabbitmq的东西,贴出服务端代码
listen代码
gen_tcp:listen(Port, SocketOpts) SocketOpts = [ binary, {packet, 0}, %%{packet, 0}表示erlang系统会吧TCP数据原封不动地直接传送给应用程序 {reuseaddr, true}, %%允许本地重复使用端口号 {nodelay, true}, %%意味着很少的数据也会被马上被发送出去 {delay_send, true}, %%如果打开了delay_send,每个port会维护一个发送队列,数据不是立即发送,而是存到发送队列里,等socket可写的时候再发送,相当于是ERTS自己实现的组包机制 {active, false}, %%注意如果socket客户端断开后,其port不会关闭,而{active,true}与{active,once}则会关闭port {backlog, 1024}, %%缓冲区的长度 {exit_on_close, false}, %%设置为flase,那么在socket被close之后还能将缓冲区中的数据发送出去 {send_timeout, 15000} %%设置一个时间去等待操作系统发送数据,如果底层在这个时间段后还没发出数据,那么就会返回{error,timeout} ]
这个handle_info是在acceptor进程处理的
handle_info({inet_async, LSock, Ref, {ok, Sock}}, State = #state{listen_socket=LSock, ref=Ref}) -> %% patch up the socket so it looks like one we got from %% gen_tcp:accept/1 {ok, Mod} = inet_db:lookup_socket(LSock), inet_db:register_socket(Sock, Mod), try %% report {ok, {Address, Port}} = inet:sockname(LSock), {ok, {PeerAddress, PeerPort}} = inet:peername(Sock), ?DEBUG("accepted TCP connection on ~s:~p from ~s:~p~n", [inet_parse:ntoa(Address), Port, inet_parse:ntoa(PeerAddress), PeerPort]), spawn_socket_controller(Sock) catch Error:Reason -> gen_tcp:close(Sock), ?ERROR_MSG("ERRunable to accept TCP connection: ~p ~p~n", [Error, Reason]) end, accept(State); spawn_socket_controller(ClientSock) -> case gen_tcp:recv(ClientSock, 23, 30000) of {ok, Bin} -> %%需要测试,过滤掉没用的数据 case supervisor:start_child(sdeeg_tcp_client_sup, [ClientSock, Line]) of {ok, CPid} -> inet:setopts(ClientSock, [{packet, 4}, binary, {active, false}, {nodelay, true}, {delay_send, true}]), gen_tcp:controlling_process(ClientSock, CPid), %%移交socket到网关进程中去 CPid ! go; %%路由到网关进程,以后的数据将会从socket发送到sdeeg_tcp_client进程 {error, Error} -> ?CRITICAL_MSG("cannt accept client:~w", [Error]), catch erlang:port_close(ClientSock) end; Other -> ?ERROR_MSG("ERRrecv packet error:~w", [Other]), catch erlang:port_close(ClientSock) end.
上面会利用gen_tcp:controlling_process把以后客户端发来的数据发送到网关进程中去处理。
下面看看网关进程的部分代码
handle_info(go, #state{socket=Socket} = State) -> prim_inet:async_recv(Socket, 0, -1), {noreply, State}; handle_info({inet_async, Socket, _Ref, {ok, Data}}, State) -> ?ERROR_MSG("ERR~p", [Data]), do_handle_data(Socket,Data,State), {noreply, State}; handle_info({inet_async, _Socket, _Ref, {error, closed}}, State) -> ?ERROR_MSG("ERR~p", [closed]), {stop, normal, State}; handle_info({inet_async, _Socket, _Ref, {error, Reason}}, State) -> ?ERROR_MSG("ERR~ts:~w", ["Socket出错", Reason]), {stop, normal, State}; do_handle_data(Socket, Data, _State) -> ?ERROR_MSG("ERR~p", [Data]), prim_inet:async_recv(Socket, 0, -1).
下面是我的测试代码:
-module(test_gateway). -export([connect/0]). connect() -> {ok,Socket1} = gen_tcp:connect("210.38.235.164", 443, [binary, {packet, 0}]), ok = gen_tcp:send(Socket1,<<1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1>>), ok = gen_tcp:send(Socket1,<<23:32,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1>>), gen_tcp:close(Socket1).
上面的测试代码只能收到第一条信息,第二条信息一直都收取不到,刚开始一直以为是ClientSocket移交给网关进程有问题,但是在执行gen_tcp:close(Socket1),网关进程却能够收到{error, closed}这条消息,明显不是这个问题。后来发现是问题是出现在这里
在刚开始gen_tcp:listen除的参数packet设置为0的,但后面把socket移交给网关进程的时候把packet设置为4.所以导致上面的客户端程序的第二条消息一直都收取不到。下面正确代码
-module(test_gateway). -export([connect/0]). connect() -> {ok,Socket1} = gen_tcp:connect("210.38.235.164", 443, [binary, {packet, 0}]), ok = gen_tcp:send(Socket1,<<1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1>>), inet:setopts(Socket1, [{packet, 4}]), ok = gen_tcp:send(Socket1,<<23:32,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1>>), gen_tcp:close(Socket1).
OK,搞定。
相关推荐
erlang入门电子书 erlang编程 Introducing Erlang,作者Simon.St.Laurent
学习erlang的时候尝试编写的小例子,使用post方式发送json数据来进行http请求,希望能帮到大家~
从 Erlang 到 CERL 到 Golang
我自己在新学erlang,在LeetCode OJ上找了题目练习,题目很适合新手熟悉语言,但是LeetCode OJ里面只有几门主流语言的答案,下面是已完成的erlang源代码,后续有空再做其他问题续传,题目包含:(源码开头都有题目...
erlang25.0 windows版本
java php python erlang 千万级内存数据性能比较,
erlang 安装包
Erlang及其应用Erlang及其应用Erlang及其应用
有些同学想把Erlang数据通过term_to_binary函数封包后以二制进形式存入数据库,然后用PHP读取并解包成PHP数组。 为了解决上面的这种应用场合中遇到的问题, 参考peb(Php-Erlang Bridge)扩展写了这个类似erlang:...
erlang文献及资料汇总 入门资料: erlang中文手册(R11B 文档译文,最适合入门) ...erlang VM内部数据共享机制 erlang 消息传递机制 文章地址:http://blog.csdn.net/mycwq/article/details/43115733
erlang otp25 win安装包
本书不适用于初学者。从大多数教程、书籍以及培训课程上所学到的知识,还...本书不要求读者知道如何调试Erlang软件,如何理解已有的代码库,如何诊断问题,以及知 道一些如何在生产环境中部署Erlang的最佳实践F 18 F。
Erlang在官网下载页面一直出现无法请求的情况,现在将下载下来的32位和64位的安装包分享
erlang22最新下载包 erlang22.1.tar.gz erlang22最新下载包 erlang22最新下载包
ErlangB和ErlangC计算工具(exe可执行文件+excel两个) ErlangB和ErlangC计算工具(exe可执行文件+excel两个)
erlang 中文基础教程erlang 中文基础教程
Erlang并发编程,Erlang程序设计,Erlang中文手册。 学习erlang的好资料。 Erlang是一个结构化,... 使用Erlang来编写分布式应用要简单的多,因为它的分布式机制是透明的:对于程序来说并不知道自己是在分布式运行。
erlang安装包
(494页带目录的高清扫描版) 这是一本讲解Erlang编程语言的入门指南,内容通俗...内容涉及模块、函数、类型、递归、错误和异常、常用数据结构、并行编程、多处理、OTP、事件处理,以及所有Erlang的重要特性和强大功能。
Programming Erlang