V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
sbmzhcn
V2EX  ›  Python

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

  •  
  •   sbmzhcn · 2015-03-21 09:09:56 +08:00 · 5125 次点击
    这是一个创建于 3534 天前的主题,其中的信息可能已经有所发展或是发生改变。
    TCPServer 如何处理客户端连接之后不发信息,然后服务器端自动给他断开呢?有没有这方面的例子,谢谢。
    13 条回复    2015-03-24 22:11:09 +08:00
    cheng007
        1
    cheng007  
       2015-03-21 11:09:42 +08:00   ❤️ 1
    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
        2
    cheng007  
       2015-03-21 11:10:28 +08:00
    代码没办法格式化,你凑合看看就好
    155
        3
    155  
       2015-03-21 11:23:00 +08:00
    recv数据和心跳包套在with gevent.Timeout里.
    wyxfcy
        4
    wyxfcy  
       2015-03-21 11:37:35 +08:00
    @155 正解。 gevent里面, socket自身的timeout无效。
    fordoo
        5
    fordoo  
       2015-03-21 21:07:12 +08:00
    x14oL
        6
    x14oL  
       2015-03-22 02:59:36 +08:00   ❤️ 1
    @cheng007 可以理解成gevent模块是真并发吗?
    yueyoum
        7
    yueyoum  
       2015-03-22 17:37:15 +08:00
    erlang 大法好
    cloudzhou
        8
    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
        9
    yueyoum  
       2015-03-23 13:47:10 +08:00
    @cloudzhou
    我没说 和语言 有关, 只是在erlang里要实现这样的功能,很容易。
    如果LZ用erlang来实现, 就不会发这样的帖子来问问题了
    cheng007
        10
    cheng007  
       2015-03-23 15:32:54 +08:00   ❤️ 1
    @x14oL 我对gevent的api不够熟悉,@155的写法是正确的。
    你可以去了解一下libevent, 还有node.js的底层库libuv,gevent并不是真正的并发,他只是利用greenlet协程封装了异步过程。
    cheng007
        11
    cheng007  
       2015-03-23 15:36:51 +08:00
    @yueyoum 我也很喜欢erlang,非常欣赏erlang的理念。
    fordoo
        12
    fordoo  
       2015-03-23 17:59:52 +08:00
    @cloudzhou 审题错误,感谢提醒。
    sbmzhcn
        13
    sbmzhcn  
    OP
       2015-03-24 22:11:09 +08:00
    感谢回复,我用的python写的一个比较简单的程序。我是希望在python代码上作一个修改就可以搞定的。
    @cloudzhou 这个做法应该是可以尝试的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2099 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:42 · PVG 08:42 · LAX 16:42 · JFK 19:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.