Erlang соответствует целому числу, а затем строке - PullRequest
0 голосов
/ 25 апреля 2018

Я хочу обновить сервер Erlang, добавив метку времени. Раньше у меня были команды, затем параметры отправлялись на сервер:

server_loop(Socket) ->
  inet:setopts(Socket, [{active, once}]),
  receive
    {tcp, Socket, <<"read", Content/binary>>} ->
      error_logger:info_msg("Reading ~w", [Content]),
      read(Socket, Content),
      server_loop(Socket);
    {tcp, Socket, <<"up", Content/binary>>} ->
      update(Socket, Content),
      server_loop(Socket);
    ...
end

Как видите, я отправляю сообщения правильным способом в зависимости от первого ключевого слова сообщения.

Теперь мой клиент отправляет метку времени (в секундах с os:system_time()) перед командой. Как я могу сопоставить свои сообщения, такие как «ANY_TIMESTAMP read», «ANY_TIMESTAMP up», ... И все же иметь возможность передать его моему методу, например read(Socket, Timestamp, Content)?

1 Ответ

0 голосов
/ 26 апреля 2018

Кодировать метку времени в префикс фиксированной длины. Вы можете выбрать, будет ли он читаемым человеком или двоичным.

make_read_packet(Timestamp, Content) ->
    <<Timestamp:64, "read", Content/bytes>>.

или

-define(TIMESTAMP_LENGTH, 20). % or any suitable size
make_read_packet(Timestamp, Content) ->
    B = integer_to_binary(Timestamp),
    P = binary:copy(<<$0>>, ?TIMESTAMP_LENGTH - byte_size(B)),
    <<P/bytes, B/bytes, "read", Content/bytes>>.

и тогда вы можете легко обнаружить его

    {tcp, Socket, <<Timestamp:64, "read", Content/binary>>} ->
      error_logger:info_msg("Reading ~w", [Content]),
      read(Socket, Timestamp, Content),
      server_loop(Socket);

или

    {tcp, Socket, <<TBin:?TIMESTAMP_LENGTH/bytes, "read", Content/binary>>} ->
      try binary_to_integer(TBin) of
        Timestamp -> 
          error_logger:info_msg("Reading ~w", [Content]),
          read(Socket, Timestamp, Content)
      catch error:badarg -> badarg end,
      server_loop(Socket);

в противном случае вам понадобится что-то вроде

  {tcp, Socket, Packet} ->
    case parse_timestamp(Packet) of
        {Timestamp, <<"read", Content/bytes>>} ->
          error_logger:info_msg("Reading ~w", [Content]),
          read(Socket, Timestamp, Content);
        _ -> error
     end,
     server_loop(Socket);

parse_timestamp(Packet) ->
    parse_timestamp(Packet, 0).

parse_timestamp(<<D, Rest/bytes>>, N) when D >= $0, D <= $9 ->
    parse_timestamp(Rest, 10 * N + D - $0);
parse_timestamp(Rest, N) -> {N, Rest}.
...