2

我无法让多个客户端与我的并发回显服务器进行通信。这是我的结果:

服务器终端窗口:

1> c(s).
{ok,s}

2> s:init(15555).
Server started on port: 15555

客户端窗口:

1> c(cl).
{ok,cl}

2> cl:test().
[<0.64.0>,<0.65.0>,<0.66.0>,<0.67.0>,<0.68.0>]

3> 
=ERROR REPORT==== 21-May-2017::21:21:39 ===
Error in process <0.68.0> with exit value:
{{badmatch,{error,econnrefused}},[{cl,client,2,[{file,"cl.erl"},{line,5}]}]}

=ERROR REPORT==== 21-May-2017::21:21:39 ===
Error in process <0.67.0> with exit value:
{{badmatch,{error,econnrefused}},[{cl,client,2,[{file,"cl.erl"},{line,5}]}]}
...
...

在shell中,如果我启动我的服务器,然后连接一个客户端,我的客户端和服务器可以来回通信而不会出错:

服务器终端窗口:

1> c(s).
{ok,s}

2> s:init(15555).
Server started on port: 15555

客户端窗口:

1> c(cl).  
{ok,cl}

2> cl:client(1, 15555).
Client1: sent -->hello
Client1: received <--hello
ok

在我失败的并发测试中,我这样做:

test() ->
    Port = 1555,
    [spawn(?MODULE, client, [Id, Port]) || Id <- lists:seq(1, 5)].

这是我的回声服务器:

-module(s).
-compile(export_all).

init(Port) ->
    {ok, ServerSocket} = gen_tcp:listen(Port, [binary, {active,true},
                                               {packet,4}, {reuseaddr,true}] ),
    io:format("Server started on port: ~w~n", [Port]),
    server(ServerSocket).

server(ServerSocket) ->
    {ok, ClientSocket} = gen_tcp:accept(ServerSocket),
    spawn(?MODULE, server, [ServerSocket]),

    timer:sleep(rand:uniform(3) * 1000),
    loop(ClientSocket).


loop(ClientSocket) ->
    receive
        {tcp, ClientSocket, CompleteMsg} ->
            io:format("Server: received ~s~n", [CompleteMsg]),
            gen_tcp:send(ClientSocket, CompleteMsg);
        {tcp_closed, ClientSocket} ->
            io:format("Server: client closed socket.~n")
    end,
    loop(ClientSocket).

这是我的客户:

-module(cl).
-compile(export_all).

client(Id, Port) ->
    {ok, Socket} = gen_tcp:connect(localhost, Port, [binary, {active,true}, 
                                                      {packet,4},
                                                      {reuseaddr, true}] ),
    Msg = "hello",
    gen_tcp:send(Socket, Msg),
    io:format("Client~w: sent -->~s~n", [Id, Msg]),

    receive 
        {tcp, Socket, CompleteMsg} ->
            io:format("Client~w: received <--~s~n", [Id, CompleteMsg]);
        {tcp_closed, Socket} ->
            io:format("Server closed the socket.~n")
    end,
    gen_tcp:close(Socket).

test() ->
    Port = 1555,
    [spawn(?MODULE, client, [Id, Port]) || Id <- lists:seq(1, 5)].

我的理解是 aTCP socket只不过是一个包含四个数字的元组:

{senderPort, senderAddress, destinationPort, destinationAddress}

我认为我的每个客户端都必须具有相同的senderPortand senderAddress,因此它们都在尝试使用相同的 TCP 套接字。但我认为我的一个客户端将能够成功建立 TCP 连接,而其余客户端则出现连接被拒绝错误,但我的所有并发客户端都出现连接被拒绝错误。

在我看来,gen_tcp:connect()以某种方式选择了一个 senderPort 并检索了 senderAddress,它与 ServerAddress 和 ServerPort 参数一起定义了套接字。如何让我的每个客户端使用不同的 senderPort,以便每个客户端创建一个唯一的套接字?

有没有办法在本地主机上以编程方式测试具有多个客户端的并发服务器?

4

0 回答 0