在Erlang中将客户端添加到列表中

时间:2013-08-07 15:25:21

标签: functional-programming erlang tuples

所以我正在编写客户端可以连接的基本服务器。我正在用telnet测试它,但我的问题是如何将我的客户端存储在列表中,这样我就可以打印出连接到服务器的人了。我已经尝试在存储客户端的列表上使用++运算符,但我一直收到进程错误。

到目前为止,这是我的代码:

cell_process()->
    io:fwrite("In cell~n"),
    {ok,Listening_socket} = gen_tcp:listen(21,
                                           [binary,
                                            {backlog,5},
                                            {active,false},
                                            {packet,line}]),
    loop(Listening_socket).

loop(Listening_socket)->
    case gen_tcp:accept(Listening_socket) of
        {ok,Client_socket} ->

            gen_tcp:send(Client_socket, "Hello, what is your name?"),
            {_,Name} = gen_tcp:recv(Client_socket,0),
            gen_tcp:send(Client_socket, "Hello, "),
            gen_tcp:send(Client_socket, Name),
            io:fwrite([Name]),
            spawn(fun()-> client_loop(Client_socket) end),
            loop(Listening_socket);

        {error,Why}->io:fwrite("Error: "),
                     io:fwrite([Why])
    end.

client_loop(Client_socket)->
    case gen_tcp:recv(Client_socket,0) of
        {ok,Message}-> gen_tcp:send(Client_socket,Message),
                       %% code not yet implemented here
                       client_loop(Client_socket);

        {error,Why}-> io:fwrite("Error: ~s~n",[Why]),
                      gen_tcp:close(Client_socket)
    end.

感谢阅读,非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

要保留已连接客户端的痕迹,您必须向循环函数添加变量,并按照建议将任何相关信息存储在客户端列表中。

cell_process()->
    io:fwrite("In cell~n"),
    {ok,Listening_socket} = gen_tcp:listen(21,
                                           [binary,
                                            {backlog,5},
                                            {active,false},
                                            {packet,line}]),
    loop(Listening_socket,[]). %% initial Clients list is empty

loop(Listening_socket,Clients)->
    case gen_tcp:accept(Listening_socket) of
        {ok,Client_socket} ->

            gen_tcp:send(Client_socket, "Hello, what is your name?"),
            {_,Name} = gen_tcp:recv(Client_socket,0),
            gen_tcp:send(Client_socket, "Hello, "),
            gen_tcp:send(Client_socket, Name),
            io:fwrite([Name]),
            Pid = spawn(fun()-> client_loop(Client_socket) end),
            loop(Listening_socket,[{Pid,Client_socket,Name}|Clients]);

%%将新客户添加到列表中但请参阅我的评论

        {error,Why}->io:fwrite("Error: "),
                     io:fwrite([Why])
    end.

client_loop(Client_socket)->
    case gen_tcp:recv(Client_socket,0) of
        {ok,Message}-> gen_tcp:send(Client_socket,Message),
                       %% code not yet implemented here
                       client_loop(Client_socket);

        {error,Why}-> io:fwrite("Error: ~s~n",[Why]),
                      gen_tcp:close(Client_socket)
    end.

注释:它不是存储客户端列表的正确位置,因为您必须使用链接或监视器来管理正在死亡的客户端,因此您需要一个与套接字侦听不兼容的接收块。所以我认为你应该添加一个服务器来管理这个列表,哪个角色是监听每次启动新客户端时发送的消息,监控客户端,当他想知道客户端列表时回答管理员... < / p>

答案 1 :(得分:1)

这是一个建议:

loop(Listening_socket, ClientList)->
    case gen_tcp:accept(Listening_socket) of
        {ok,Client_socket} ->
            gen_tcp:send(Client_socket, "Hello, what is your name?"),
            {_,Name} = gen_tcp:recv(Client_socket,0),
            gen_tcp:send(Client_socket, "Hello, "),
            gen_tcp:send(Client_socket, Name),
            io:fwrite([Name]),
            spawn(fun()-> client_loop(Client_socket) end),
            loop(Listening_socket, [Client_socket | ClientList]);

        {error,Why}->io:fwrite("Error: "),
                     io:fwrite([Why])
    end.

更好的解决方案是使用state记录存储所需的所有变量(在本例中为Listening_socket和ClientList)并使用state循环。