Erlang03_套接字编程(2) UDP
总篇:12
编辑于 2025/5/8 22:00
截稿于: 2025/5/8 23:30
上一篇实现了简单的TCP服务器客户端通信,接下来学习UDP
简介
Upd无需建立连接,因此无需listen,accept等操作,服务器只需要open一个Socket,然后无论谁都可以向其send数据,需要时也可手动close。
原语
gen_udp 模块:
- {ok,Socket} = open(Port,[binary])
{ok,Socket} = open(Port,[binary]),服务器监听Port端口(0是随机端口),数据以二进制形式传输
- ok =send(Socket,Host,Port,Bin)
ok =send(Socket,Host,Port,Bin), 服务器/客户端的Socket向Host,Port发送Bin数据包,
监听此端口的Socket接受到消息
- close(Socket)
close(Socket),关闭Socket,释放资源
简单的Udp通信
- 异步开启一个监听Port的服务器,监听到Port接受消息后打印,返回给客户端ok。
- 客户端随机监听一个端口打开Socket,向服务端端口发送消息,在接收到服务端返回的ok或者超时2s后,打印结果。
- 服务器的Socket没有关闭,可以继续生成客户端向其发送数据。
-module(socket_udp).
-export([start_server/1, client/2]).
start_server(Port) ->
spawn(fun() -> server(Port) end).
server(Port) ->
{ok, Socket} = gen_udp:open(Port, [binary]),
loop(Socket).
loop(Socket) ->
receive
{udp, Socket, Host, Port, Bin} ->
% 处理接收到的二进制数据
Data = binary_to_term(Bin),
io:format("received data: ~p~n", [Data]),
BinReply = term_to_binary(ok),
% 发送响应回客户端
gen_udp:send(Socket, Host, Port, BinReply),
loop(Socket)
end.
client(Port, Request) ->
{ok, Socket} = gen_udp:open(0, [binary]),
ok = gen_udp:send(Socket, "localhost", Port, Request),
Value =
receive
{udp, Socket, _, _, Bin} ->
binary_to_term(Bin)
after 2000 ->
error
end,
% 关闭socket
gen_udp:close(Socket),
Value.
正常执行

error,因为没有监听1234端口的Socket,客户端无法得到回应

Udp因为其不保证消息可靠,可能会出现数据包丢失、错位。如果需要使用Udp来达到消息正确处理,需要用到"make_ref()", 该BIF会生成全球范围内唯一的一个引用Ref,充当详细的Id,客户端发送消息的时候携带Ref,服务端处理完消息后返回时也携带该Ref就能达到数据正确处理的效果。将以上代码改造:
- 客户端向服务端发送带Ref的数字
- 服务端接收到Ref和数子,返回Ref和数字的平方
- 客户端接收服务器发送的消息,只有Ref与其发送的Ref匹配的时候才接收,不同则error
-module(socket_udp).
-export([start_server/1, client/2]).
start_server(Port) ->
spawn(fun() -> server(Port) end).
server(Port) ->
{ok, Socket} = gen_udp:open(Port, [binary]),
loop(Socket).
loop(Socket) ->
receive
{udp, Socket, Host, Port, Bin} ->
{Ref, Number} = binary_to_term(Bin),
Result = Number * Number,
BinReply = term_to_binary({Ref, Result}),
gen_udp:send(Socket, Host, Port, BinReply),
loop(Socket)
end.
client(Port, Number) when is_number(Number) ->
{ok, Socket} = gen_udp:open(0, [binary]),
Ref = make_ref(),
Request = term_to_binary({Ref, Number}),
ok = gen_udp:send(Socket, "localhost", Port, Request),
Value =
receive
{udp, Socket, _, _, Bin} ->
case binary_to_term(Bin) of
% 服务器返回的引用和客户端发送的应用匹配时才接收
{Ref, Result} -> Result;
_ -> {error, wrong_ref}
end
after 2000 ->
{error, timeout}
end,
gen_udp:close(Socket),
Value.

关于套接字先认识到这里。
浙公网安备 33010602011771号