代码之家  ›  专栏  ›  技术社区  ›  nmichaels

gen_tcp smushed消息[重复]

  •  5
  • nmichaels  · 技术社区  · 14 年前

    我正在使用来自 this 客户机和服务器的教程和以下代码:

    服务器:

    -module(echo_server).
    -export([start/0, loop/1]).
    
    % echo_server specific code
    start() ->
        spawn(socket_server, start, [?MODULE, 7000, {?MODULE, loop}]).
    
    loop(Socket) ->
        case gen_tcp:recv(Socket, 0) of
            {ok, Message} ->
                Msg = binary_to_term(Message),
                case Msg of
                    start ->
                        io:format("Got start message on socket ~p.~n", [Socket]),
                        send_count(Socket, 10),
                        gen_tcp:close(Socket);
                    Other ->
                        io:format("Got message on socket ~p: ~p~n",
                                  [Socket, Other])
                end;
            {error, closed} ->
                io:format("Got closed message on socket ~p.~n", [Socket]),
                ok;
            Error ->
                io:format("Got bad message: ~p on socket ~p.~n", [Error, Socket])
        end.
    
    send_count(_Socket, 0) ->
        ok;
    send_count(Socket, Num) ->
        io:format("Sending ~p to ~p.~n", [Num, Socket]),
        gen_tcp:send(Socket, term_to_binary(Num)),
        send_count(Socket, Num - 1).
    

    客户:

    -module(echo_client).
    -export([start/0, do_stuff/0]).
    
    
    send(Socket, Msg) ->
        gen_tcp:send(Socket, term_to_binary(Msg)).
    
    start() ->
        dbg:tracer(),
        Pid = spawn(?MODULE, do_stuff, []),
        dbg:p(Pid, r).
    
    do_stuff() ->
        case gen_tcp:connect("localhost", 7000, [binary, {packet, 0}]) of
            {ok, Socket} ->
                send(Socket, start),
                rx_loop(Socket);
            Error ->
                io:format("Error connecting to server: ~p~n", [Error])
        end.
    
    rx_loop(Socket) ->
        receive
            {tcp, Socket, Message} ->
                Msg = binary_to_term(Message),
                io:format("Received message: ~p~n", [Msg]),
                rx_loop(Socket)
        after 5000 ->
                finish_loop(Socket)
        end.
    
    finish_loop(Socket) ->
        receive
            {tcp, Socket, Message} ->
                Msg = binary_to_term(Message),
                io:format("Received message: ~p~n", [Msg]),
                rx_loop(Socket);
            {tcp_closed, Socket} ->
                io:format("Server terminated connection.~n"),
                exit(normal);
            Error ->
                io:format("Received bad message: ~p~n", [Error]),
                rx_loop(Socket)
        end.
    

    我在召唤 echo_server:start() echo_client:start() 从同一系统的不同外壳,按顺序排列。我看到的是:

    服务器似乎工作正常。

    1>echo_server:start().
    <0.39.0>
    Got start message on socket #Port<0.2041>.
    Sending 10 to #Port<0.2041>.
    Sending 9 to #Port<0.2041>.
    Sending 8 to #Port<0.2041>.
    Sending 7 to #Port<0.2041>.
    Sending 6 to #Port<0.2041>.
    Sending 5 to #Port<0.2041>.
    Sending 4 to #Port<0.2041>.
    Sending 3 to #Port<0.2041>.
    Sending 2 to #Port<0.2041>.
    Sending 1 to #Port<0.2041>.
    

    客户端没有完全正确地获取所有消息:

    2> echo_client:start().
    {ok,[{matched,nonode@nohost,1}]}
    3> (<0.41.0>) << {code_server,{module,gen_tcp}}
    (<0.41.0>) << {code_server,{module,inet_tcp}}
    (<0.41.0>) << {#Ref<0.0.0.74>,{ok,<0.43.0>}}
    (<0.41.0>) << {#Ref<0.0.0.76>,
                   {ok,<<4,0,0,0,2,127,0,0,1,127,0,0,1,0,0,0,3,108,111,99,97,108,
                         104,111,115,116,0,105,112,54,45,108,111,99,97,108,104,
                         111,115,116,0,105,112,54,45,108,111,111,112,98,97,99,
                         107,0>>}}
    (<0.41.0>) << {inet_async,#Port<0.2058>,0,ok}
    (<0.41.0>) << {inet_reply,#Port<0.2058>,ok}
    Received message: 10
    3> (<0.41.0>) << {tcp,#Port<0.2058>,<<131,97,10>>}
    Received message: 9
    3> (<0.41.0>) << {io_reply,<0.25.0>,ok}
    (<0.41.0>) << timeout
    (<0.41.0>) << {tcp,#Port<0.2058>,<<131,97,9>>}
    (<0.41.0>) << {io_reply,<0.25.0>,ok}
    Received message: 8
    Received message: 5
    Received message: 4
    Received message: 3
    Received message: 2
    Received message: 1
    3> (<0.41.0>) << timeout
    (<0.41.0>) << {tcp,#Port<0.2058>,<<131,97,8,131,97,7,131,97,6>>} %% <---This guy here
    (<0.41.0>) << {io_reply,<0.25.0>,ok}
    (<0.41.0>) << {tcp,#Port<0.2058>,<<131,97,5>>}
    (<0.41.0>) << timeout
    (<0.41.0>) << {io_reply,<0.25.0>,ok}
    (<0.41.0>) << timeout
    (<0.41.0>) << {tcp,#Port<0.2058>,<<131,97,4>>}
    (<0.41.0>) << {io_reply,<0.25.0>,ok}
    (<0.41.0>) << timeout
    (<0.41.0>) << {tcp,#Port<0.2058>,<<131,97,3>>}
    (<0.41.0>) << {io_reply,<0.25.0>,ok}
    (<0.41.0>) << timeout
    (<0.41.0>) << {tcp,#Port<0.2058>,<<131,97,2>>}
    (<0.41.0>) << {io_reply,<0.25.0>,ok}
    (<0.41.0>) << timeout
    (<0.41.0>) << {tcp,#Port<0.2058>,<<131,97,1>>}
    (<0.41.0>) << {io_reply,<0.25.0>,ok}
    (<0.41.0>) << {tcp_closed,#Port<0.2058>}
    (<0.41.0>) << timeout
    Server terminated connection.
    3> (<0.41.0>) << timeout
    (<0.41.0>) << {io_reply,<0.25.0>,ok}
    (<0.41.0>) << timeout
    

    如果我查看网络流量 lo ,我看到每一个倒数都有干净的PSH/ACK对。上面我指的那一行显示了在一条消息中出现的两个包:7和6。它们作为两个独立的TCP数据包通过网络。有人知道他们为什么会一起被玷污,或者如何消除他们的污点吗?

    1 回复  |  直到 14 年前
        1
  •  7
  •   Jim Lewis    14 年前

    为什么它们在接收端被“弄脏”:因为TCP是一种流协议, 而且不要求send/recv呼叫与 网络数据包(即使它们是通过网络到达的)。

    如何“去除污点”:或者更改TCP协议以包含消息分隔符, 因此您可以从流中提取消息,而无需知道数据包的位置 边界是;或者使用UDP而不是TCP。

    推荐文章