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
wowpanda
V2EX  ›  Python

请教关于 python 简单的 socket 服务器端的问题

  •  
  •   wowpanda · 2015-06-01 23:34:15 +08:00 · 3532 次点击
    这是一个创建于 3461 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在做一个简单的数据库,现在想实现通过网络来访问数据库。从客户端传送数据到服务器端,然后服务器端执行相应的操作。
    我是建立一个socket,然后服务器开始无限循环,每次接收一个连接就开一个线程,然后由这个线程去操作数据库。
    请问这个线程去操作数据库这一步要怎么做呢?
    也是 while True:
    data=socket.recv(maxsize)
    result=database_operation(data)
    socket.send(result)
    这个思路吗? 这里的maxsize怎么设置?recv是阻塞的,如果客户端发送数据频率高的话,会出现客户端发送过来的数据成了一团浆糊啊。
    另外,怎么保持连接的时间?因为客户端操作的时间间隔肯定会很长,这个线程一直要这样循环下去吗?
    ps:渣渣基础不好,求聚聚们轻喷。

    15 条回复    2015-06-03 11:27:04 +08:00
    ryd994
        1
    ryd994  
       2015-06-02 02:13:18 +08:00 via Android
    你可以参考标准库 https://docs.python.org/2/library/socketserver.html
    CPython源码网上有
    你需要实时性的话就不要阻塞,反复查然后判断有没有数据,设置socket选项即可
    tcp连接一般不需要特意保持,只要不关闭文件符就会一直开着。对于部分防火墙路由器可能需要keepalive,同样是设置socket选项即可
    ryd994
        2
    ryd994  
       2015-06-02 02:15:09 +08:00 via Android
    另外你这样性能估计不好,需要性能的话要用epoll/gevent之类的
    clino
        3
    clino  
       2015-06-02 07:19:12 +08:00 via Android
    建议用 http 更好
    wowpanda
        4
    wowpanda  
    OP
       2015-06-02 09:58:06 +08:00
    @ryd994
    我查了一些epoll的资料,大致思路是:
    while True:
    if event & select.EPOLLIN:
    data=connections[fileno].recv(maxsize)
    result=database_operation(data)
    epoll.modify(fileno, select.EPOLLOUT)
    elif event & select.EPOLLOUT:
    connections[fileno].send(result)
    epoll.modify(fileno, select.EPOLLIN)
    请问这么做,有没有什么问题?
    wowpanda
        5
    wowpanda  
    OP
       2015-06-02 09:58:31 +08:00
    @clino 用requests库来做?
    clino
        6
    clino  
       2015-06-02 10:09:33 +08:00
    @wowpanda 我是说用提供 http api 的方式,客户端以访问 http api 的方式来调用服务端的服务
    这样你的服务端程序只要考虑处理 request返回 response,并发调度之类的可以中间放一个nginx之类的web服务器来做
    mulog
        7
    mulog  
       2015-06-02 10:13:40 +08:00
    > 这里的maxsize怎么设置?recv是阻塞的,如果客户端发送数据频率高的话,会出现客户端发送过来的数据成了一团浆糊啊。

    不会啊 你要用裸 socket 做的话肯定得自定一个简单协议 做好 message 之间的分割就好了
    clino
        8
    clino  
       2015-06-02 10:19:53 +08:00
    或者如果web方面完全无基础可以先不考虑我的建议

    上面gevent的建议,这里有简单例子: http://xlambda.com/gevent-tutorial/#server
    gevent对于并发多io高的情况,因为是用协程方式实现的有占用资源较少支持并发较高的优点
    wowpanda
        9
    wowpanda  
    OP
       2015-06-02 10:32:48 +08:00
    @clino http api,我的理解是,用tornado库,访问一个url,然后返回数据
    clino
        10
    clino  
       2015-06-02 10:38:32 +08:00
    @wowpanda 随便找个web框架就行,只是提供api估计都比较简单都差不多,如果涉及到其他方面差别就比较大了
    另外像tornado这种本身是异步的所以对高并发本身支持得应该就比较好,像我用的uliweb则可以用gevent方式部署
    fangjinmin
        11
    fangjinmin  
       2015-06-02 12:47:23 +08:00
    用epoll吧,epoll的效率更高。
    zenliver
        12
    zenliver  
       2015-06-02 16:00:13 +08:00
    tornado有个tcpserver, 拿来用啊, 自己瞎捣鼓什么
    ryd994
        13
    ryd994  
       2015-06-03 02:41:48 +08:00 via Android
    @wowpanda epoll或者gevent的库很多啊,比如greenlet之类的,基本上用法都是直接import代替原版就可
    cloudzhou
        14
    cloudzhou  
       2015-06-03 10:16:23 +08:00
    使用 gevent
    Karblue
        15
    Karblue  
       2015-06-03 11:27:04 +08:00
    epoll & iocp 同步操作肯定效率低
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2783 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 14:19 · PVG 22:19 · LAX 06:19 · JFK 09:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.