Erlang02_并发编程(4) 基于套接字的分布式模式
总篇:10
编辑于 2025/5/6 20:30
截稿于: 2025/5/6 22:10
简介
套接字(Socket),IP+Port,连接两台终端设备的“插槽”,使用套接字主要是为了相互可信的设备连通。
原语
gen模块:
-
{ok,ListenSocket} =listen(Port [
binary,
{packet, 0},
{active, true},
]) 启动服务器
listen(Port [ % 端口号
binary, % 以二进制形式处理数据
{packet, 0}, % 原始数据模式,不自动处理包长度
{active, true}, % 主动模式,自动将数据转为消息发送给进程
{reuseaddr, true} % 允许重用地址,快速重启服务器
])
在Port启动一个服务
-
{ok,Socket} =connect("localhost", ServerPort, [
binary, {packet, 0}, {active, true}]) 客户第连接服务器
connect(
"localhost", % 主机地址
ServerPort, % 服务器端口号
[
binary, % 以二进制形式处理数据
{packet, 0}, % 原始数据模式
{active, true}% 主动模式
]
)
返回的是{ok,Socket实例}
- accept(ClientSocket)
{ok, Socket} = accept(ClientSocket),
- send(Socket, term_to_binary(Data)) 消息发送
send(Socket, term_to_binary(Data))
通过Socket发送消息,客户端向服务器发送,以二进制数据的形式发送。
聊天室修改为套接字
-module(chat_server).
-export([start/1]).
start(Port) ->
{ok, ListenSocket} = gen_tcp:listen(Port, [binary, {packet, 0},
{active, true},
{reuseaddr, true}]),
io:format("Chat server started on port ~p~n", [Port]),
acceptor(ListenSocket, #{}).
acceptor(ListenSocket, Clients) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
spawn(fun() -> acceptor(ListenSocket, Clients) end),
loop(Socket, Clients).
loop(Socket, Clients) ->
receive
{tcp, Socket, <<"REGISTER:", Name/binary>>} ->
io:format("New client registered: ~p~n", [Name]),
NewClients = maps:put(Socket, Name, Clients),
loop(Socket, NewClients);
{tcp, Socket, Data} ->
case maps:get(Socket, Clients, undefined) of
undefined ->
io:format("Message from unregistered client: ~p~n", [Data]),
loop(Socket, Clients);
Name ->
broadcast_message(Name, Data, maps:to_list(Clients)),
loop(Socket, Clients)
end;
{tcp_closed, Socket} ->
case maps:get(Socket, Clients, undefined) of
undefined -> ok;
Name -> io:format("Client ~p disconnected~n", [Name])
end,
NewClients = maps:remove(Socket, Clients),
loop(Socket, NewClients);
Other ->
io:format("Received unknown message: ~p~n", [Other]),
loop(Socket, Clients)
end.
broadcast_message(From, Message, ClientList) ->
io:format("Broadcasting message from ~p: ~p~n", [From, Message]),
lists:foreach(fun({Socket, _Name}) ->
gen_tcp:send(Socket, <<From/binary, ":", Message/binary>>)
end, ClientList).
-module(chater).
-export([start/3, send_message/2]).
start(Name, Host, Port) ->
case gen_tcp:connect(Host, Port, [binary, {packet, 0}, {active, true}]) of
{ok, Socket} ->
% 首先发送注册消息
Registration = <<"REGISTER:", Name/binary>>,
gen_tcp:send(Socket, Registration),
Pid = spawn(fun() -> loop(Name, Socket) end),
{ok, Pid, Socket};
{error, Reason} ->
{error, Reason}
end.
send_message(Socket, Message) when is_binary(Message) ->
gen_tcp:send(Socket, Message);
send_message(Socket, Message) ->
gen_tcp:send(Socket, term_to_binary(Message)).
loop(Name, Socket) ->
receive
{tcp, Socket, Data} ->
io:format("~p Received message: ~p~n", [Name, Data]),
loop(Name, Socket);
{tcp_closed, Socket} ->
io:format("~p: Server closed connection~n", [Name]),
exit(normal);
{tcp_error, Socket, Reason} ->
io:format("~p: TCP Error: ~p~n", [Name, Reason]),
exit(Reason)
end.



以上程序存在以下问题:
消息只能发送给服务端,客户端无法接受其他客户端发送来的消息
浙公网安备 33010602011771号