TCP 套接字关闭但未被进程检测到
TCP socket closing but not detected by process
我有一个允许连接的服务器,然后根据它收到的消息,服务器应该做一些事情(目前还没有实现)但是如果套接字关闭,服务器也应该提醒我它没有。
sloop(Listen)->
{ok, Socket} = gen_tcp:accept(Listen),
io:format("Someone connected"),
master ! {add,Socket},
io:format("Point A reached"),
spawn(fun() -> sloop(Listen) end),
io:format("Point B reached"),
receive
{tcp, Socket, Bin} ->
case read(Bin) of
{join,Channel} ->
tracker ! {self(),get,Socket},
receive
void ->
master ! {delete, Socket},
A = lists:dropwhile(fun(A) -> A /= Channel end, registered()),
case A of
[H|_] -> H ! {add,Socket};
_ -> register(Channel,spawn(fun() -> listenerSocket([]) end))
end,
Channel ! {add, Socket},
tracker ! {insert,Socket, Channel};
{ok, Value} ->
Value ! {delete,Socket},
tracker ! {delete,Socket},
A = lists:dropwhile(fun(A) -> A /= Channel end, registered()),
case A of
[H|_] -> H ! {add,Socket};
_ -> register(Channel,spawn(fun() -> listenerSocket([]) end))
end,
Channel ! {add, Socket},
tracker ! {insert,Socket, Channel};
{message, Msg} ->
tracker ! {self(),get,Socket},
receive
{ok, Value} -> Value ! {broadcast, Msg}
end
end;
{tcp_closed, Socket} -> io:format("Someone disconnected")
end
end.
每当我打开一个套接字并将其指向 localhost:2266 时,shell 打印 "Someone connected" 、 "Point A reached"、"Point B reached" 但是每当我关闭套接字时使用 tcp_gen:close/1
服务器不打印 "Someone disconnected".
修复代码的格式可能会有所帮助,因为这会告诉您 {tcp_closed, Socket}
模式匹配是 case
子句,而不是 receive
子句。我认为您打算将其作为最外层 receive
.
的子句
请注意 sloop/1
函数不是递归的,这意味着它的最外层 receive
仅处理一条消息,处理该消息,然后 returns。也许你有其他代码你没有显示重复调用 sloop/1
,但无论哪种方式,你都需要某种循环遍历 sloop/1
,同时将你的 {tcp_closed, Socket}
模式匹配移动到最外层receive
,让您的应用程序正确处理多条消息。
您需要递归调用您的侦听器函数。如前所述,侦听器函数将在第一条消息后终止,因此不会侦听 gen_tcp:close
消息。处理成功消息后重新进入循环即可。
sloop(Listen)->
{ok, Socket} = gen_tcp:accept(Listen),
io:format("Someone connected"),
master ! {add,Socket}, % <-- not sure what this does
io:format("Point A reached"),
spawn(fun() -> sloop(Listen) end),
io:format("Point B reached").
loop_internal(Socket) ->
inet:setopts(Socket,[{active,once}]),
receive
{tcp, Socket, Bin} ->
do_your_stuff(Bin),
%% your stuff removed for brevity
loop_internal(Socket);
{tcp_closed, Socket} -> io:format("Someone disconnected")
end
end.
我有一个允许连接的服务器,然后根据它收到的消息,服务器应该做一些事情(目前还没有实现)但是如果套接字关闭,服务器也应该提醒我它没有。
sloop(Listen)->
{ok, Socket} = gen_tcp:accept(Listen),
io:format("Someone connected"),
master ! {add,Socket},
io:format("Point A reached"),
spawn(fun() -> sloop(Listen) end),
io:format("Point B reached"),
receive
{tcp, Socket, Bin} ->
case read(Bin) of
{join,Channel} ->
tracker ! {self(),get,Socket},
receive
void ->
master ! {delete, Socket},
A = lists:dropwhile(fun(A) -> A /= Channel end, registered()),
case A of
[H|_] -> H ! {add,Socket};
_ -> register(Channel,spawn(fun() -> listenerSocket([]) end))
end,
Channel ! {add, Socket},
tracker ! {insert,Socket, Channel};
{ok, Value} ->
Value ! {delete,Socket},
tracker ! {delete,Socket},
A = lists:dropwhile(fun(A) -> A /= Channel end, registered()),
case A of
[H|_] -> H ! {add,Socket};
_ -> register(Channel,spawn(fun() -> listenerSocket([]) end))
end,
Channel ! {add, Socket},
tracker ! {insert,Socket, Channel};
{message, Msg} ->
tracker ! {self(),get,Socket},
receive
{ok, Value} -> Value ! {broadcast, Msg}
end
end;
{tcp_closed, Socket} -> io:format("Someone disconnected")
end
end.
每当我打开一个套接字并将其指向 localhost:2266 时,shell 打印 "Someone connected" 、 "Point A reached"、"Point B reached" 但是每当我关闭套接字时使用 tcp_gen:close/1
服务器不打印 "Someone disconnected".
修复代码的格式可能会有所帮助,因为这会告诉您 {tcp_closed, Socket}
模式匹配是 case
子句,而不是 receive
子句。我认为您打算将其作为最外层 receive
.
请注意 sloop/1
函数不是递归的,这意味着它的最外层 receive
仅处理一条消息,处理该消息,然后 returns。也许你有其他代码你没有显示重复调用 sloop/1
,但无论哪种方式,你都需要某种循环遍历 sloop/1
,同时将你的 {tcp_closed, Socket}
模式匹配移动到最外层receive
,让您的应用程序正确处理多条消息。
您需要递归调用您的侦听器函数。如前所述,侦听器函数将在第一条消息后终止,因此不会侦听 gen_tcp:close
消息。处理成功消息后重新进入循环即可。
sloop(Listen)->
{ok, Socket} = gen_tcp:accept(Listen),
io:format("Someone connected"),
master ! {add,Socket}, % <-- not sure what this does
io:format("Point A reached"),
spawn(fun() -> sloop(Listen) end),
io:format("Point B reached").
loop_internal(Socket) ->
inet:setopts(Socket,[{active,once}]),
receive
{tcp, Socket, Bin} ->
do_your_stuff(Bin),
%% your stuff removed for brevity
loop_internal(Socket);
{tcp_closed, Socket} -> io:format("Someone disconnected")
end
end.