【问题标题】:Erlang: {packet,N} option works for N = 0 but not 1,2,4?Erlang:{packet,N} 选项适用于 N = 0 但不适用于 1、2、4?
【发布时间】:2013-03-15 12:15:10
【问题描述】:

以下代码适用于 gen_tcp:connect() 函数调用中的 {packet,0} 选项,但不适用于 1 、 2 和 4 (尽管我只测试了 4 并且我假设 1 和 2 也不起作用)。我的问题是为什么不使用一个而不是另一个重要?基本上,Erlang 文档没有详细解释有关数据包选项的主题,Joe Armstrong 的 Programming Erlang 也没有提供任何详细信息;他只是解释说数据包没有按顺序重新组装,尽管我一直认为 tcp 数据包在发送时被接收,这与 UDP 不同。我有一个有趣的注释是this page 上的客户端-服务器有{packet,4} 作为选项,它工作正常并且与下面的代码非常相似。这是下面代码中使用的{packet,4} 选项的服务器外壳输出。

Erlang R16A (erts-5.10) [smp:8:8] [async-threads:10]

Eshell V5.10  (abort with ^G)
1> cd("c:/erlang").
c:/erlang
ok
2> c(cp3).
{ok,cp3}
3> cp3:server().
Started Server:
<0.41.0>
Accept Server:
Pid <0.43.0>
Connection accepted 
Accept Server:
Loop Server:
Error on socket #Port<0.2256> reason: einval

这是客户端的 shell 输出。

Erlang R16A (erts-5.10) [smp:8:8] [async-threads:10]

Eshell V5.10  (abort with ^G)
1> cd("c:/erlang").
c:/erlang
ok
2> cp3:client().
exit
3> 

这是使用的代码,

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

client() ->
    {ok, Socket} =  gen_tcp:connect("localhost", 4001,[binary, {packet, 4}]),
    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, 4},{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) ->   
    io:format("Loop Server:~n"),
    case gen_tcp:recv(Socket, 6) 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 erlang client-server option packet


    【解决方案1】:

    您的代码几乎没问题,只需在循环(套接字)中修改该行

    case gen_tcp:recv(Socket, 6) of

    通过

    case gen_tcp:recv(Socket, 0) of

    查看文档:

    recv(Socket, Length) -> {ok, Packet} | {error, Reason} recv(Socket,Length, Timeout) -> {ok, Packet} | {错误,原因}

    类型:Socket = socket() Length = integer() >= 0 Timeout = timeout() 数据包 = 字符串() |二进制() | HttpPacket 原因 = 关闭 | inet:posix() HttpPacket = term() 见 HttpPacket 中的描述 erlang:decode_packet/3.

    此函数以被动模式从套接字接收数据包。一种 关闭的套接字由返回值 {error, closed} 指示。

    Length 参数仅在套接字处于原始模式时才有意义,表示要读取的字节数。如果长度 = 0, 返回所有可用字节。如果 Length > 0,则返回正好 Length 字节, 或错误;可能丢弃小于 Length 字节的数据时 套接字从另一侧关闭。

    可选的 Timeout 参数以毫秒为单位指定超时。 默认值为无穷大。

    通过此修改它可以工作,但是由于客户端在每次调用后关闭套接字,您会收到一条错误消息,我不确定从客户端关闭套接字是否有用。您可以通过以下方式修改客户端来更改此行为:

    client() ->
        {ok, Socket} =  gen_tcp:connect("localhost", 4001,[binary, {packet, 4}]),
        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.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      相关资源
      最近更新 更多