【问题标题】:Erlang: gen_tcp:recv() does not receive packet sent from client?Erlang:gen_tcp:recv() 没有收到客户端发送的数据包?
【发布时间】:2013-03-14 18:38:42
【问题描述】:

我修改了this server 以使用gen_tcp:recv,以便将数据包的字节数限制为50。我注释掉了inet:setopts(Socket, [{active, once}]), 行,因为gen_tcp:recv 应该是{active,false}。这是客户端的erl shell

2> cp3:client().
exit
3> 

这是服务器端的 erl shell

4> cp3:server().
Started Server:
<0.46.0>
Accept Server:
Pid <0.48.0>
Connection accepted 
Accept Server:
Loop Server:
5> 

我还想知道如果gen_tcp:recv 没有创建一个套接字,我怎么知道套接字是否以返回值{tcp_closed, Socket} 关闭?

-module(cp3).
-export([client/0, server/0,start/0,accept/1,enter_loop/1,loop/1]).

client() ->
    {ok, Socket} =  gen_tcp:connect("localhost", 4001,[list, {packet, 0}]),
    ok = gen_tcp:send(Socket, "packet"),
    receive
        {tcp,Socket,String} ->
            io:format("Client received = ~p~n",[String]),       
            io:format("Client result = ~p~n",[String]),
            gen_tcp:close(Socket)
        after 1000 ->
            exit        
    end.

server() -> 
    Pid = spawn(fun()-> start() end),
    Pid.

start() ->  
    io:format("Started Server:~n"),
    {ok, Socket} = gen_tcp:listen(4001, [binary, {packet, 0},{reuseaddr, true},{active, false}]),
    accept(Socket).

accept(ListenSocket) ->
    io:format("Accept Server:~n"),
    case gen_tcp:accept(ListenSocket) of
        {ok, Socket} ->
            Pid = spawn(fun() ->
                io:format("Connection accepted ~n", []),
                enter_loop(Socket)
            end),
            io:format("Pid ~p~n",[Pid]),
            gen_tcp:controlling_process(Socket, Pid),
            Pid ! ack,
            accept(ListenSocket);
        Error ->
            exit(Error)
    end.

enter_loop(Socket) ->
    %% make sure to acknowledge owner rights transmission finished
    receive ack -> ok end,
    loop(Socket).

loop(Socket) ->
    %% set socket options to receive messages directly into itself
    %%inet:setopts(Socket, [{active, once}]),
    io:format("Loop Server:~n"),
    case gen_tcp:recv(Socket, 50) of
    {ok, Data} ->  
        case Data of
            <<"packet">> ->                 
                io:format("Server replying = ~p~n",[Data]),   
                gen_tcp:send(Socket, Data),
                loop(Socket)                  
        end;
    {error, Reason} ->      
        io:format("Error on socket ~p reason: ~p~n", [Socket, Reason])          
    end.

【问题讨论】:

  • 对不起,我不太明白你的问题。在活动套接字中,当套接字关闭时,控制进程将发送{tcp_closed,Socket} 消息,而对于被动套接字,调用gen_tcp:recv 将返回{error,closed}。 “activeness”是为每一端设置的,并且可以是不同的。如果 Erlang 之外的套接字的另一端无关,如何处理。
  • 好的,我还有一个问题,这是一个并行服务器是否意味着它会为每个连接的客户端生成一个新进程?
  • 是的。函数accept/1 位于递归循环中。它调用gen_tcp:accept,当它返回一个新的数据套接字时,它会产生一个在该连接上运行enter_loop/1 的新进程。然后它移交对套接字的控制权,对gen_tcp:controlling_process/2 的调用,然后递归地调用它以等待它产生一个新进程来处理的新连接,等等。这个过程一直持续到gen_tcp:accept 返回一个错误并且函数终止。这是为每个连接创建新进程的常用方法。

标签: erlang client-server limit packet gen-tcp


【解决方案1】:

我不是很清楚你的问题,但是上面的代码不起作用。希望以下内容能解答您的问题。您的 tcp 接收 case gen_tcp:recv(Socket, 50) of 有一个错误。它正在等待读取 50 个字节。查看gen_tcp:recv/2 的文档。将长度(packer 6 的长度,但最好改为)0 以接收所有字节。

该值不限制数据的大小,但在接收到长度为50的数据之前,它不会发回数据。相反,您可能需要接受然后检查它。

【讨论】:

  • 你是对的,这就是我所需要的,它只是 Erlangs 的文档已经得到了非常详细的解释,我认为任何超过 recv 中设置的限制的数据包都会被丢弃,我没有注意到任何解释不会将任何内容发送回客户端。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-30
  • 2019-12-27
  • 1970-01-01
  • 2014-12-27
  • 2019-09-07
相关资源
最近更新 更多