Я разрабатываю приложение для чата, использующее передачу сообщений. Я хочу передать сообщение всем присоединившимся клиентам, когда новый клиент присоединяется к той же комнате. Коды, которые я использую следующим образом:
клиент.erl
{join, Roomname} ->
{?SERVER, ?SERVER_NODE} ! {self(), {join, Roomname}},
receive
{joined, Roomname, RoomPid, Messages} ->
...... Do something
loop(UpdatedState);
{failed, Why} ->
io:format("~p ~n", [Why]),
loop(S)
after ?TIMEOUT ->
io:format("No response from server or chatroom ~n", [])
end
чат-рум.erl
{join, ClientPid, ClientName} ->
UpdatedClients = orddict:store(ClientPid,
ClientName,S#state.clients),
Roomname = S#state.name,
Messages = S#state.messages,
ClientPid ! {joined, Roomname, self(), Messages},
loop(S#state{clients=UpdatedClients});
сервер.erl
{Client, {join, Roomname}} ->
Rooms = S#state.rooms,
RoomExist = orddict:is_key(Roomname, Rooms),
if RoomExist ->
RoomPid = orddict:fetch(Roomname, Rooms),
Clientname = orddict:fetch(Client, S#state.clients),
RoomPid ! {join, Client, Clientname},
io:format("~p joined room ~p ~n", [Clientname, Roomname]);
not RoomExist ->
Client ! {failed, room_does_not_exist}
end,
loop(S);
Коды выше работают нормально. Однако я попытался передать сообщение всем присоединившимся клиентам, когда новый клиент присоединяется к той же комнате, изменив client.erl
и chatrroom.erl
на:
клиент.erl
{join, Roomname} ->
{?SERVER, ?SERVER_NODE} ! {self(), {join, Roomname}},
receive
{joined, Roomname, RoomPid, Messages} ->
...... Do something
loop(UpdatedState);
{broadcast,Who,Roomname} ->
io:format("~p Joined room ~p ~n", [Who,Roomname]);
{failed, Why} ->
io:format("~p ~n", [Why]),
loop(S)
after ?TIMEOUT ->
io:format("No response from server or chatroom ~n", [])
end
чат-рум.erl
{join, ClientPid, ClientName} ->
Clients = S#state.clients,
ClientPids = orddict:fetch_keys(Clients),
UpdatedClients = orddict:store(ClientPid, ClientName,S#state.clients),
Roomname = S#state.name,
Messages = S#state.messages,
ClientPid ! {joined, Roomname, self(), Messages},
[Pid ! {broadcast,ClientName,Roomname} || Pid <- ClientPids],
loop(S#state{clients=UpdatedClients});
присоединение нового клиента все еще работает нормально, но я получаю «Неизвестное сообщение» в процессах присоединенных клиентов, например:
Unknown message: {broadcast,the new client name,the room name}
Это значит, что первое сообщение ClientPid ! {joined, Roomname, self(), Messages}
распознается, а второе [Pid ! {broadcast,ClientName,Roomname} || Pid <- ClientPids]
нет!
Что плохого я здесь делаю?
Вам следует проверить, появляется ли это сообщение об ошибке на втором Pid. Если да, то, вероятно, это потому, что вы пропустили loop(XXX)
в предложении receive
.
Чтобы отследить, что происходит внутри блока приема, вы можете следовать этому подходу, реструктурируя код и распечатывая сообщение / то есть значение «Другое».
...
receive
Msg ->
handle_message(Msg)
after ?TIMEOUT ->
io:format("No response from server or chatroom ~n", [])
...
...
handle_message({joined, Roomname, RoomPid, Messages}) ->
...... Do something
loop(UpdatedState);
handle_message({broadcast, Who, Roomname}) ->
io:format("~p Joined room ~p~n", [Who, Roomname]),
loop(S);
handle_message({failed, Why}) ->
io:format("~p~n", [Why]),
loop(S);
handle_message(Other) ->
io:format("Other case apparently: ~p~n", [Other]),
loop(S).
обновил мой ответ
На самом деле, код, который я опубликовал, представляет собой часть длинных функций внутри предложения получения. По некоторым причинам мне не разрешено использовать поведение, предложенное в статье. Я сделал что-то вроде Unknown -> io:format("Unknown message: ~p~n", [Unknown]), loop(S) end.
Проблема в том, что подключенные клиенты (или, скажем, второй клиент, которому должно транслироваться сообщение) не распознают сообщение {broadcast,ClientName,Roomname}
Ага, я понял! большое спасибо !
Да, сообщение появляется на уже присоединенных PID. Я изменил код на
{broadcast,Who,Roomname} -> io:format("~p Joined room ~p ~n", [Who,Roomname]),loop(S);
. Но возникает та же ошибка