erlang异步接收不到数据的问题

主要是利用rabbitmq的东西,贴出服务端代码

listen代码

Java代码   收藏代码
  1. gen_tcp:listen(Port, SocketOpts)  
  2.   
  3. SocketOpts = [  
  4.                    binary,   
  5.                    {packet, 0}, %%{packet, 0}表示erlang系统会吧TCP数据原封不动地直接传送给应用程序  
  6.                    {reuseaddr, true},  %%允许本地重复使用端口号  
  7.                    {nodelay, true},  %%意味着很少的数据也会被马上被发送出去   
  8.                    {delay_send, true},  %%如果打开了delay_send,每个port会维护一个发送队列,数据不是立即发送,而是存到发送队列里,等socket可写的时候再发送,相当于是ERTS自己实现的组包机制  
  9.                    {active, false}, %%注意如果socket客户端断开后,其port不会关闭,而{active,true}与{active,once}则会关闭port  
  10.                    {backlog, 1024}, %%缓冲区的长度  
  11.                    {exit_on_close, false}, %%设置为flase,那么在socket被close之后还能将缓冲区中的数据发送出去  
  12.                    {send_timeout, 15000} %%设置一个时间去等待操作系统发送数据,如果底层在这个时间段后还没发出数据,那么就会返回{error,timeout}  
  13.                   ]  

 

这个handle_info是在acceptor进程处理的

 

Java代码   收藏代码
  1. handle_info({inet_async, LSock, Ref, {ok, Sock}}, State = #state{listen_socket=LSock, ref=Ref}) ->  
  2.     %% patch up the socket so it looks like one we got from  
  3.     %% gen_tcp:accept/1  
  4.     {ok, Mod} = inet_db:lookup_socket(LSock),  
  5.     inet_db:register_socket(Sock, Mod),  
  6.     try          
  7.         %% report  
  8.         {ok, {Address, Port}} = inet:sockname(LSock),  
  9.         {ok, {PeerAddress, PeerPort}} = inet:peername(Sock),  
  10.         ?DEBUG("accepted TCP connection on ~s:~p from ~s:~p~n",  
  11.                     [inet_parse:ntoa(Address), Port,  
  12.                      inet_parse:ntoa(PeerAddress), PeerPort]),  
  13.         spawn_socket_controller(Sock)  
  14.     catch Error:Reason ->  
  15.             gen_tcp:close(Sock),  
  16.             ?ERROR_MSG("ERRunable to accept TCP connection: ~p ~p~n", [Error, Reason])  
  17.     end,  
  18.     accept(State);  
  19.   
  20. spawn_socket_controller(ClientSock) ->  
  21.     case gen_tcp:recv(ClientSock, 2330000) of  
  22.         {ok, Bin} -> %%需要测试,过滤掉没用的数据  
  23.             case supervisor:start_child(sdeeg_tcp_client_sup, [ClientSock, Line]) of  
  24.                 {ok, CPid} ->  
  25.                     inet:setopts(ClientSock, [{packet, 4}, binary, {active, false}, {nodelay, true}, {delay_send, true}]),  
  26.                     gen_tcp:controlling_process(ClientSock, CPid), %%移交socket到网关进程中去  
  27.                     CPid ! go; %%路由到网关进程,以后的数据将会从socket发送到sdeeg_tcp_client进程  
  28.                 {error, Error} ->  
  29.                     ?CRITICAL_MSG("cannt accept client:~w", [Error]),  
  30.                     catch erlang:port_close(ClientSock)  
  31.             end;  
  32.         Other ->  
  33.             ?ERROR_MSG("ERRrecv packet error:~w", [Other]),  
  34.             catch erlang:port_close(ClientSock)  
  35.     end.  

 上面会利用gen_tcp:controlling_process把以后客户端发来的数据发送到网关进程中去处理。

 

 下面看看网关进程的部分代码

Java代码   收藏代码
  1. handle_info(go, #state{socket=Socket} = State) ->  
  2.     prim_inet:async_recv(Socket, 0, -1),  
  3.     {noreply, State};  
  4.   
  5.   
  6. handle_info({inet_async, Socket, _Ref, {ok, Data}}, State) ->  
  7.     ?ERROR_MSG("ERR~p", [Data]),  
  8.     do_handle_data(Socket,Data,State),  
  9.     {noreply, State};  
  10.   
  11. handle_info({inet_async, _Socket, _Ref, {error, closed}}, State) ->  
  12.     ?ERROR_MSG("ERR~p", [closed]),  
  13.     {stop, normal, State};  
  14.       
  15. handle_info({inet_async, _Socket, _Ref, {error, Reason}}, State) ->  
  16.     ?ERROR_MSG("ERR~ts:~w", ["Socket出错", Reason]),  
  17.     {stop, normal, State};  
  18.   
  19. do_handle_data(Socket, Data, _State) ->  
  20.   ?ERROR_MSG("ERR~p", [Data]),  
  21.   prim_inet:async_recv(Socket, 0, -1).  

 

 

下面是我的测试代码:

Java代码   收藏代码
  1. -module(test_gateway).  
  2. -export([connect/0]).  
  3.   
  4. connect() ->  
  5.     {ok,Socket1} = gen_tcp:connect("210.38.235.164"443, [binary, {packet, 0}]),  
  6.     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>>),  
  7.     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>>),  
  8.     gen_tcp:close(Socket1).  

 上面的测试代码只能收到第一条信息,第二条信息一直都收取不到,刚开始一直以为是ClientSocket移交给网关进程有问题,但是在执行gen_tcp:close(Socket1),网关进程却能够收到{error, closed}这条消息,明显不是这个问题。后来发现是问题是出现在这里

在刚开始gen_tcp:listen除的参数packet设置为0的,但后面把socket移交给网关进程的时候把packet设置为4.所以导致上面的客户端程序的第二条消息一直都收取不到。下面正确代码

Java代码   收藏代码
  1. -module(test_gateway).  
  2. -export([connect/0]).  
  3.   
  4. connect() ->  
  5.     {ok,Socket1} = gen_tcp:connect("210.38.235.164"443, [binary, {packet, 0}]),  
  6.     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>>),  
  7.     inet:setopts(Socket1, [{packet, 4}]),  
  8.     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>>),  
  9.     gen_tcp:close(Socket1).  

 OK,搞定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值