TCP 套接字关闭但未被进程检测到
Posted
技术标签:
【中文标题】TCP 套接字关闭但未被进程检测到【英文标题】:TCP socket closing but not detected by process 【发布时间】:2015-09-14 06:35:40 【问题描述】:我有一个允许连接的服务器,然后根据它接收到的消息,服务器应该做一些事情(目前尚未实现)但是如果套接字关闭,服务器也应该提醒我它没有不。
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
关闭套接字时,服务器不会打印“有人断开连接”。
【问题讨论】:
原子master
和tracker
是变量吗?
已注册的进程
【参考方案1】:
修复代码的格式可能会有所帮助,因为这会显示您的 tcp_closed, Socket
模式匹配是 case
子句,而不是 receive
子句。我认为您打算将其作为最外层receive
的子句。
注意sloop/1
函数不是递归的,这意味着它最外层的receive
只处理一条消息,处理该消息,然后返回。也许您有其他代码没有显示重复调用sloop/1
,但无论哪种方式,您都需要通过sloop/1
进行某种循环,同时将您的tcp_closed, Socket
模式匹配移动到最外面的receive
,以允许您的应用程序可以正确处理多条消息。
【讨论】:
我很抱歉,但我根本无法发现。tcp_closed, Socket
后面有两端。一个用于接收,一个用于功能。如果它是case
的子句,肯定会有另一个end
?也许我在这里看不太清楚。是的。我确实有一些东西可以让这个过程保持活力。
普通函数没有end
。最后的end
匹配最外面的receive
,它上面的匹配case
,而tcp_closed, Socket
正上方的end
匹配紧随join,Channel
之后开始的receive
。
啊...为什么我会认为函数有终点。谢谢【参考方案2】:
您需要递归调用侦听器函数。如所写,监听函数将在第一条消息后终止,因此不会监听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.
【讨论】:
以上是关于TCP 套接字关闭但未被进程检测到的主要内容,如果未能解决你的问题,请参考以下文章
TCP套接字:检测对等方是不是在发送前关闭? (Linux)