Erlang整数后匹配字符串及服务器添加时间戳改造技术咨询
我来帮你搞定Erlang服务器的这两个需求——时间戳功能和先匹配整数再匹配字符串的消息解析,直接上实用的实现方案:
实现Erlang服务器的时间戳功能与消息解析逻辑
一、先匹配整数再匹配字符串的消息解析
你需要先把收到的二进制消息拆解成命令、整数参数和字符串参数,Erlang的二进制模式匹配是处理这类场景的绝佳工具。我们可以写一个通用的解析函数,来处理这种"命令 + 整数 + 字符串"的格式:
parse_message(<<"read ", IntBin/binary, " ", StrBin/binary>>) -> try Int = binary_to_integer(IntBin), {read, Int, StrBin} catch _:_ -> {invalid_message, <<"read command requires integer + string">>} end; parse_message(<<"up ", IntBin/binary, " ", StrBin/binary>>) -> try Int = binary_to_integer(IntBin), {up, Int, StrBin} catch _:_ -> {invalid_message, <<"up command requires integer + string">>} end; parse_message(Other) -> {unknown_command, Other}.
这个函数会尝试把命令后的第一个参数转成整数,剩下的部分作为字符串参数,如果转换失败会返回错误信息,方便后续给客户端反馈。
二、添加时间戳功能
Erlang提供了erlang:system_time/1来获取高精度时间戳,你可以根据需求选择精度(比如millisecond或microsecond)。我们可以把时间戳集成到日志记录和业务处理中:
- 获取可读时间戳的工具函数:
get_timestamp() -> % 生成YYYY-MM-DD HH:MM:SS.ms格式的可读时间戳 {Date, Time} = calendar:local_time(), {Hour, Min, Sec} = Time, Ms = erlang:system_time(millisecond) rem 1000, lists:flatten(io_lib:format("~p ~2..0w:~2..0w:~2..0w.~3..0w", [Date, Hour, Min, Sec, Ms])).
这个函数返回的字符串适合直接写到日志里,或者返回给客户端展示操作时间。
- 在业务逻辑中集成时间戳:
比如修改你的update和read函数,加入时间戳的记录和使用:
update(Socket, IntParam, StrParam) -> Timestamp = get_timestamp(), % 记录带时间戳的操作日志 error_logger:info_msg("[~s] Executing update with int: ~w, str: ~w", [Timestamp, IntParam, StrParam]), % 这里写你的业务更新逻辑,比如把时间戳和参数一起存储 % 示例:给客户端返回带时间戳的响应 gen_tcp:send(Socket, <<"Updated at ", (list_to_binary(Timestamp))/binary, ", params: ", integer_to_binary(IntParam), " ", StrParam/binary>>). read(Socket, IntParam, StrParam) -> Timestamp = get_timestamp(), error_logger:info_msg("[~s] Reading with int: ~w, str: ~w", [Timestamp, IntParam, StrParam]), % 读取逻辑... gen_tcp:send(Socket, <<"Read at ", (list_to_binary(Timestamp))/binary, ", result: ...">>).
三、整合到server_loop主循环
现在把解析函数和时间戳功能整合到你的原有循环里,修改后的server_loop会先解析消息,再分发到对应的处理函数,同时处理异常情况:
server_loop(Socket) -> inet:setopts(Socket, [{active, once}]), receive {tcp, Socket, Data} -> case parse_message(Data) of {read, IntParam, StrParam} -> read(Socket, IntParam, StrParam), server_loop(Socket); {up, IntParam, StrParam} -> update(Socket, IntParam, StrParam), server_loop(Socket); {invalid_message, ErrMsg} -> gen_tcp:send(Socket, <<"Error: ", ErrMsg/binary>>), server_loop(Socket); {unknown_command, Cmd} -> error_logger:warning_msg("Unknown command received: ~w", [Cmd]), gen_tcp:send(Socket, <<"Unknown command">>), server_loop(Socket) end; {tcp_closed, Socket} -> error_logger:info_msg("Client socket closed"), ok; {tcp_error, Socket, Reason} -> error_logger:error_msg("TCP error occurred: ~w", [Reason]), ok end.
额外提示
- 如果你的消息格式不是空格分隔(比如固定长度的整数),可以调整
parse_message里的二进制匹配规则,比如<<"up", IntBin:4/binary, StrBin/binary>>(假设整数占4字节),但空格分隔的方式更灵活通用。 - 如果你需要纯数字格式的时间戳(比如存储到数据库),直接用
erlang:system_time(millisecond)返回整数即可,不需要转换为字符串。 - 新增的
tcp_closed和tcp_error处理能让你的服务器更健壮,避免异常退出。
内容的提问来源于stack exchange,提问作者Dranna
相关产品推荐
相关产品推荐

