Я устанавливаю сокет-соединение с локальным хостом.Я хотел бы получить входные данные от сервера по этому соединению (или по любому соединению, но использование того же соединения казалось самым простым решением).Поскольку несколько клиентов смогут подключаться к моему серверу, я создал функцию входа в систему, которая, помимо прочего, будет создавать поток, который прослушивает сообщения, отправленные с сервера.
Когда я ввожу команды
c(erlSoc).
erlSoc:logon("Jacob").
Я получаю сообщение об ошибке
[C] error {error,einval}
Я знаю, что эта строка
E ->
io:format("[C] error ~p~n", [E])
печатаетэто, но что мне нужно изменить, чтобы эта ошибка не возникала, и я мог получать сообщения с сервера.
Основная достопримечательность от erlSoc.erl
logon(Uname) ->
{ok, Sock} = gen_tcp:connect("localhost", 5300, [binary, {packet, 0}]),
spawn(erlSoc, client_receive, [Sock]),
io:format("Create a Room: create~nList Rooms: list~nJoin Rooms: join~n Leave Rooms: leave~nSend a message: message ~n"),
client(Sock, Uname).
client_receive(Sock) ->
case gen_tcp:recv(Sock, 0) of
{ok, Data} ->
io:format("[C] ~p~n", [Data]);
{error, closed} ->
io:format("[C] closed~n", []);
E ->
io:format("[C] error ~p~n", [E])
end.
erlSoc.erl
-module(erlSoc).
-export([start_server/0, logon/1, remove/2, server/1, client_receive/1]).
-define(TCP_OPTIONS, [binary, {packet, 0}, {active, false}, {reuseaddr, true}]).
listen() ->
{ok, LSocket} = gen_tcp:listen(5300, ?TCP_OPTIONS),
io:format("Accepted the socket connection ~n"),
accept(LSocket).
accept(LSocket) ->
{ok, CSocket} = gen_tcp:accept(LSocket),
Ref = make_ref(),
To = spawn(fun() -> init(Ref, CSocket) end),
gen_tcp:controlling_process(CSocket, To),
To ! {handoff, Ref, CSocket},
io:format("Second Test ~n"),
accept(LSocket).
init(Ref, Socket) ->
receive
{handoff, Ref, Socket} ->
{ok, Peername} = inet:peername(Socket),
io:format("[S] peername ~p~n", [Peername]),
loop(Socket)
end.
loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
List = binary_to_list(Data),
List2 = string:tokens(List,","),
io:format("[S] got ~p~n", [List2]),
parse_data(Socket, List2),
loop(Socket);
{error, closed} ->
io:format("[S] closed~n", []);
E ->
io:format("[S] error ~p~n", [E])
end.
server_node() ->
erlSoc@localhost.
parse_data(Soc, [Task, Rname | Message]) ->
if
Task =:= "message" ->
{erlSoc, self()} ! {message, Rname, Message};
Task =:= "create" ->
{erlSoc, server_node()} ! {create, Rname, Soc};
Task =:= "list" ->
{erlSoc, self()} ! {list, Soc};
Task =:= "join" ->
{erlSoc, self()} ! {join, Rname, Soc};
Task =:= "leave" ->
{erlSoc, self()} ! {leave, Rname, Soc}
end.
start_server() ->
spawn(erlSoc, server, [[[]]]),
listen().
remove(X, L) ->
[Y || Y <- L, Y =/= X].
server(RoomList) ->
receive
{message, Rname, Message} ->
[_|[Users|Messages]] = lists:keyfind(Rname, 1, RoomList),
RoomUpdate = lists:keyreplace(Rname, 1, RoomList, [Rname|[Users|[Messages|Message]]]),
send_message(Message, Rname, Users),
server(RoomUpdate);
{create, Rname, Soc} ->
server([[Rname|[Soc|[]]]|RoomList]);
{list, Soc} ->
{Rooms, _} = RoomList,
gen_tcp:send(Soc,Rooms),
server(RoomList);
{join, Rname, User} ->
[Room|[Users|Messages]] = lists:keyfind(Rname, 1, RoomList),
RoomUpdate = lists:keyreplace(Rname, 1, RoomList, [Rname|[[Users|User]|[Messages]]]),
gen_tcp:send(User,[Rname,Messages]),
[Room|[Users|Messages]] = lists:keyfind(Rname, 1, RoomUpdate),
io:format("Users in ~p : ~p~n", [Rname, Users]),
server(RoomList);
{leave, Rname, User} ->
[Room|[Users|Messages]] = lists:keyfind(Rname, 1, RoomList),
NewU = remove(User, Users),
RoomUpdate = lists:keyreplace(Rname, 1, RoomList, [Rname|[[NewU]|[Messages]]]),
[Room|[Users|Messages]] = lists:keyfind(Rname, 1, RoomUpdate),
io:format("Users in ~p : ~p~n", [Rname, Users]),
server(RoomUpdate)
end.
send_message(Message, ChatRoom, []) ->
void;
send_message(Message, Chatroom, [To|Users]) ->
gen_tcp:send(To,"Message From Chatroom "++Chatroom++": "++Message),
send_message(Message, Chatroom, Users).
logon(Uname) ->
{ok, Sock} = gen_tcp:connect("localhost", 5300, [binary, {packet, 0}]),
spawn(erlSoc, client_receive, [Sock]),
io:format("Create a Room: create~nList Rooms: list~nJoin Rooms: join~n Leave Rooms: leave~nSend a message: message ~n"),
client(Sock, Uname).
client_receive(Sock) ->
case gen_tcp:recv(Sock, 0) of
{ok, Data} ->
io:format("[C] ~p~n", [Data]);
{error, closed} ->
io:format("[C] closed~n", []);
E ->
io:format("[C] error ~p~n", [E])
end.
client(Sock, Uname) ->
{ok,[Task]} = io:fread("Task? : ", "~s"),
if
Task =:= "message" ->
{ok, [Rname]} = io:fread("Send the message to which room? : ", "~s"),
Message = io:get_line("Type your message: "),
ok = gen_tcp:send(Sock,"message,"++Rname++","++Uname++": "++Message);
Task =:= "create" ->
{ok, [Rname]} = io:fread("Enter a room name : ", "~s"),
ok = gen_tcp:send(Sock, "create,"++Rname);
Task =:= "list" ->
ok = gen_tcp:send(Sock, "list");
Task =:= "join" ->
{ok, [Rname]} = io:fread("Leave Which Room? : ", "~s"),
ok = gen_tcp:send(Sock, "leave,"++Rname);
Task =:= "leave" ->
{ok, [Rname]} = io:fread("Join Which Room? : ", "~s"),
ok = gen_tcp:send(Sock, "join,"++Rname);
Task =:= "help" ->
io:format("Create a Room: create~nList Rooms: list~nJoin Rooms: join~n Leave Rooms: leave~nSend a message: message ~n");
Task =:= "exit" ->
gen_tcp:close(Sock)
end.
Обновление
-module(erlSoc).
-export([start_server/0, logon/1, remove/2, server/1, client_receive/1, client/2]).
-define(TCP_OPTIONS, [binary, {packet, 0}, {active, false}, {reuseaddr, true}]).
listen() ->
{ok, LSocket} = gen_tcp:listen(5300, ?TCP_OPTIONS),
io:format("Accepted the socket connection ~n"),
accept(LSocket).
accept(LSocket) ->
{ok, CSocket} = gen_tcp:accept(LSocket),
Ref = make_ref(),
To = spawn(fun() -> init(Ref, CSocket) end),
gen_tcp:controlling_process(CSocket, To),
To ! {handoff, Ref, CSocket},
io:format("Second Test ~n"),
accept(LSocket).
init(Ref, Socket) ->
receive
{handoff, Ref, Socket} ->
{ok, Peername} = inet:peername(Socket),
io:format("[S] peername ~p~n", [Peername]),
loop(Socket)
end.
loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
List = binary_to_list(Data),
List2 = string:tokens(List,","),
io:format("[S] got ~p~n", [List2]),
parse_data(Socket, List2),
loop(Socket);
{error, closed} ->
io:format("[S] closed~n", []);
E ->
io:format("[S] error ~p~n", [E])
end.
server_node() ->
erlSoc@localhost.
parse_data(Soc, [Task, Rname | Message]) ->
case Task of
"message" ->
{erlSoc, server_node()} ! {message, Rname, Message};
"create" ->
io:format("[C] ~p~n", [Rname]),
{erlSoc, server_node()} ! {create, Rname, Soc};
"list" ->
{erlSoc, server_node()} ! {list, Soc};
"join" ->
{erlSoc, server_node()} ! {join, Rname, Soc};
"leave" ->
{erlSoc, server_node()} ! {leave, Rname, Soc}
end.
start_server() ->
spawn(erlSoc, server, [[[]]]),
listen().
remove(X, L) ->
[Y || Y <- L, Y =/= X].
server(RoomList) ->
receive
{message, Rname, Message} ->
[_|[Users|Messages]] = lists:keyfind(Rname, 1, RoomList),
RoomUpdate = lists:keyreplace(Rname, 1, RoomList, [Rname|[Users|[Messages|Message]]]),
send_message(Message, Rname, Users),
server(RoomUpdate);
{create, Rname, Soc} ->
server([[Rname|[Soc|[]]]|RoomList]),
io:format("[C] ~p~n", [Rname]);
{list, Soc} ->
{Rooms, _} = RoomList,
gen_tcp:send(Soc,Rooms),
server(RoomList);
{join, Rname, User} ->
[Room|[Users|Messages]] = lists:keyfind(Rname, 1, RoomList),
RoomUpdate = lists:keyreplace(Rname, 1, RoomList, [Rname|[[Users|User]|[Messages]]]),
gen_tcp:send(User,[Rname,Messages]),
[Room|[Users|Messages]] = lists:keyfind(Rname, 1, RoomUpdate),
io:format("Users in ~p : ~p~n", [Rname, Users]),
server(RoomList);
{leave, Rname, User} ->
[Room|[Users|Messages]] = lists:keyfind(Rname, 1, RoomList),
NewU = remove(User, Users),
RoomUpdate = lists:keyreplace(Rname, 1, RoomList, [Rname|[[NewU]|[Messages]]]),
[Room|[Users|Messages]] = lists:keyfind(Rname, 1, RoomUpdate),
io:format("Users in ~p : ~p~n", [Rname, Users]),
server(RoomUpdate)
end.
send_message(Message, ChatRoom, []) ->
void;
send_message(Message, Chatroom, [To|Users]) ->
gen_tcp:send(To,"Message From Chatroom "++Chatroom++": "++Message),
send_message(Message, Chatroom, Users).
logon(Uname) ->
{ok, Sock} = gen_tcp:connect("localhost", 5300, [binary, {packet, 0}, {active, false}]),
Merp = spawn(erlSoc, client_receive, [Sock]),
gen_tcp:controlling_process(Sock, Merp),
io:format("Create a Room: create~nList Rooms: list~nJoin Rooms: join~n Leave Rooms: leave~nSend a message: message ~n"),
Raph = spawn(erlSoc, client, [Sock, Uname]),
gen_tcp:controlling_process(Sock, Raph).
client_receive(Sock) ->
case gen_tcp:recv(Sock, 0) of
{ok, Data} ->
io:format("[C] ~p~n", [Data]),
client_receive(Sock);
{error, closed} ->
io:format("[C] closed~n", []);
E ->
io:format("[C] error ~p~n", [E])
end.
client(Sock, Uname) ->
{ok,[Task]} = io:fread("Task? : ", "~s"),
if
Task =:= "message" ->
{ok, [Rname]} = io:fread("Send the message to which room? : ", "~s"),
Message = io:get_line("Type your message: "),
ok = gen_tcp:send(Sock,"message,"++Rname++","++Uname++": "++Message);
Task =:= "create" ->
{ok, [Rname]} = io:fread("Enter a room name : ", "~s"),
ok = gen_tcp:send(Sock, "create,"++Rname);
Task =:= "list" ->
ok = gen_tcp:send(Sock, "list");
Task =:= "join" ->
{ok, [Rname]} = io:fread("Leave Which Room? : ", "~s"),
ok = gen_tcp:send(Sock, "leave,"++Rname);
Task =:= "leave" ->
{ok, [Rname]} = io:fread("Join Which Room? : ", "~s"),
ok = gen_tcp:send(Sock, "join,"++Rname);
Task =:= "help" ->
io:format("Create a Room: create~nList Rooms: list~nJoin Rooms: join~n Leave Rooms: leave~nSend a message: message ~n");
Task =:= "exit" ->
gen_tcp:close(Sock)
end,
client(Sock,Uname).