gevent + TCPServer(StreamServer) 当客户端长久不发信息时,如何自动断开当前连接

2015-03-21 09:09:56 +08:00
 sbmzhcn
TCPServer 如何处理客户端连接之后不发信息,然后服务器端自动给他断开呢?有没有这方面的例子,谢谢。
5156 次点击
所在节点    Python
13 条回复
cheng007
2015-03-21 11:09:42 +08:00
bSendData = False

def check(fd):
while True:
gevent.sleep(30)
#check socket
if bSendData:
bSendData = false
else:
# close socket fd
fd.close()

def recv(fd):
while True:
data = fd.recv(100)
if len(data) <= 0:
return
else:
bSendData = True

gevent.spawn(recv, fd)
gevent.spawn(check,fd)
你可以为每条连接创建一个协程定时检查,这段时间客户端没有发数据。
大致如此,就是消耗有点大,需要多创建一个协程了
cheng007
2015-03-21 11:10:28 +08:00
代码没办法格式化,你凑合看看就好
155
2015-03-21 11:23:00 +08:00
recv数据和心跳包套在with gevent.Timeout里.
wyxfcy
2015-03-21 11:37:35 +08:00
@155 正解。 gevent里面, socket自身的timeout无效。
fordoo
2015-03-21 21:07:12 +08:00
x14oL
2015-03-22 02:59:36 +08:00
@cheng007 可以理解成gevent模块是真并发吗?
yueyoum
2015-03-22 17:37:15 +08:00
erlang 大法好
cloudzhou
2015-03-23 11:42:36 +08:00
@yueyoum 这种模型和语言无关的,和设计有关。
@fordoo keep-alive选项是很好的选择,但是keep-alive是协议里面支持的,为的是保证链接可用,而不是问题里面提到的:长久不发信息,就断掉链接。

比较环保的一种做法是:
维护一个 lru cache, connection 就是 key。
当每个链接接受到新的数据之后,更新 connection 当前时间,lru 更新。
当 lur 超过一定长度,从某个时间段之后,强制断掉之后的 connection。

可以使用 redis 来做这件事情,File descriptor 作为 key, 但是需要保持 File descriptor -> connection 的映射。
yueyoum
2015-03-23 13:47:10 +08:00
@cloudzhou
我没说 和语言 有关, 只是在erlang里要实现这样的功能,很容易。
如果LZ用erlang来实现, 就不会发这样的帖子来问问题了
cheng007
2015-03-23 15:32:54 +08:00
@x14oL 我对gevent的api不够熟悉,@155的写法是正确的。
你可以去了解一下libevent, 还有node.js的底层库libuv,gevent并不是真正的并发,他只是利用greenlet协程封装了异步过程。
cheng007
2015-03-23 15:36:51 +08:00
@yueyoum 我也很喜欢erlang,非常欣赏erlang的理念。
fordoo
2015-03-23 17:59:52 +08:00
@cloudzhou 审题错误,感谢提醒。
sbmzhcn
2015-03-24 22:11:09 +08:00
感谢回复,我用的python写的一个比较简单的程序。我是希望在python代码上作一个修改就可以搞定的。
@cloudzhou 这个做法应该是可以尝试的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/178376

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX