我无法让多个客户端与我的并发echo服务器通信。以下是我的结果:
服务器终端窗口:
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)].
这是我的echo服务器:
-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)].
我的理解是TCP socket
只不过是一个包含四个数字的元组:
{senderPort, senderAddress, destinationPort, destinationAddress}
我认为我的每个客户端必须具有相同的senderPort
和senderAddress
,因此他们都在尝试使用相同的TCP套接字。但我认为我的一个客户端能够成功建立TCP连接,而其余客户端连接被拒绝错误,但我的所有并发客户端都拒绝连接错误。
在我看来,gen_tcp:connect()
以某种方式选择senderPort并检索senderAddress,它与ServerAddress和ServerPort参数一起定义了套接字。如何让每个客户端使用不同的senderPort,以便每个客户端创建一个唯一的套接字?
有没有办法以编程方式测试localhost上有多个客户端的并发服务器?