當我運行我的服務器和客戶端時,服務器收到一個請求,但是當調用protocol/3方法時,它只是停止。我用調試器進行了檢查,它只是在函數調用上,但沒有任何反應。目前的典型運行如下所示:服務器沒有收到請求後繼續
server:start().
S = client:start().
client:authenticate(S, "Anon").
此時它只是停止工作。請注意,我在兩個獨立的erlang外殼上運行服務器和客戶端。
Server代碼
start() ->
io:format("Starting Server..."),
Clients = dict:new(),
Database = spawn_link(fun() -> database(Clients)end),
case gen_tcp:listen(1992, [binary, {active, false}]) of
{ok, ListeningSocket} ->
io:format("ok~n"),
accept(ListeningSocket, Database),
{ok, Port} = inet:port(ListeningSocket);
{error, Reason} ->
io:format("Failed: ~s", [Reason]),
{error, Reason}
end.
database(Clients) ->
receive
{get_client, From, User} ->
case dict:find(User, Clients) of
{ok, UserSocket} ->
From ! {id, UserSocket};
error ->
From ! error
end,
database(Clients);
{ins_client, From, Socket, User} ->
case dict:find(User, Clients) of
{ok, _} ->
From ! error;
error ->
Updated = dict:store(User, Socket, Clients),
From ! ok,
database(Updated)
end
end.
accept(ListeningSocket, Database) ->
io:format("Accepting..."),
case gen_tcp:accept(ListeningSocket) of
{ok, Socket} ->
io:format("ok~n"),
Pid = spawn(fun() -> loop(Socket, Database)end),
gen_tcp:controlling_process(Socket, Pid);
{error, Reason} ->
io:format("Failed: ~s", [Reason])
end,
accept(ListeningSocket, Database).
loop(Socket, Database) ->
inet:setopts(Socket, [{active, once}]),
io:format("Waiting for request~n"),
receive
{tcp, Socket, Data} ->
Request = binary_to_term(Data),
protocol(Socket, Request, Database),
loop(Socket, Database);
{tcp_closed, Socket} ->
io:format("Socket ~s closed. ~n", [Socket]),
gen_tcp:close(Socket)
end.
stop(Socket) ->
gen_tcp:close(Socket).
protocol(Socket, Request, Database) ->
case Request of
{message, To, Message} ->
io:format("Message received: for ~s ~s", [To, Message]),
Database ! {get_client, self(), To},
receive
{id, Receiver} ->
gen_tcp:send(Receiver, term_to_binary(Message)),
io:format("Sent to ~s: ~s~n", [Receiver, Message]);
error ->
gen_tcp:send(Socket, term_to_binary("User not found"))
end;
{enter, User} ->
io:format("Request: {Enter: ~s}", User),
Database ! {ins_client, self(), User},
receive
ok ->
gen_tcp:send(Socket, term_to_binary("Authenticated"));
error ->
gen_tcp:send(Socket, term_to_binary("Authentication failed"))
end;
Other ->
io:format("This happened: ~s", [Other])
end.
客戶端代碼
start() ->
io:format("Client starting..."),
case gen_tcp:connect({127,0,0,1}, 1992, [binary, {active, false}]) of
{ok, Socket} ->
io:format("ok.\n"),
spawn(fun() -> loop(Socket)end),
Socket;
{error, Reason} ->
io:format("Failed: ~s", [Reason]),
{error, Reason}
end.
loop(Socket) ->
inet:setopts(Socket, [{active, once}]),
io:format("Waiting for data...~n"),
receive
{tcp_closed, Socket} ->
io:format("Server ended connection.~n"),
disconnect(Socket);
{tcp, Socket, Data} ->
io:format("From Server:' ~s' ~n", [Data])
end.
authenticate(Socket, Username) ->
inet:setopts(Socket, [{active, once}]),
Term = {enter, Username},
Request = term_to_binary(Term),
gen_tcp:send(Socket, Request).
send(Socket, To, Input) ->
inet:setopts(Socket, [{active, once}]),
Message = term_to_binary({message, To, Input}),
gen_tcp:send(Socket, Message).
disconnect(Socket) ->
gen_tcp:close(Socket).
對不起任何格式錯誤,我仍然很新的這:)
非常感謝你,我知道我的問題,我會成爲這樣的事情......不幸的是它發生在每個人身上非常感謝您的回答,因爲您不僅回答了我的問題,還幫助了我的其餘申請。不勝感激! – Bangosushi
但是,我有一個循環函數的問題。正如你可能從我的代碼中看到的那樣,我不是功能編程領域的強大程序員,特別是Erlang。我如何讓我的客戶端不僅能夠調用函數(例如來自用戶),還能夠打印出消息。因爲我需要返回Socket才能使用特定的客戶端,但是我無法在產生的進程中使用print語句。 – Bangosushi
要回答你的問題,需要知道你是否期望你的客戶端能夠接收不是作爲回覆的消息,而是被動地接收服務器?如果是這樣,你應該考慮使用'gen_server',因爲它可以接受調用(例如調用來發送套接字上的東西),同時還監聽和處理傳入的消息。這需要'gen_server'進程成爲套接字的控制進程。順便說一句,你可以在產生的進程中調用'io:format',但是當然如果它們試圖同時發送文本,它的輸出可能會與其他進程的輸出混雜在一起。 –