I am making a socket connection to a localhost. I would like to receive input back from from the server on this connection(or any connection, but using the same connection seemed like the easiest solution). Because several clients will be able to connect to my server I created a logon function, which among other things, will spawn a thread that listens for messages sent from the server.
When I enter in the commands
c(erlSoc).
erlSoc:logon("Jacob").
I receive the error
[C] error {error,einval}
I know that this line
E ->
io:format("[C] error ~p~n", [E])
is printing it, but what do I need to change so that this error doesn't happen and I'm able to receive messages from the server.
Main point of Interest from 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.
Update
-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).