Python 的 socket 多线程问题,求大神解答

2017-06-13 22:33:20 +08:00
 ray1888

最近开始搞 Python 的网络编程,在写 FTP 服务器。然后基础功能都可以了(项目的目录还没优化),但是不知道怎么使可以使得多个客户端接入,怎样添加多线程或多进程才能是项目可以支持多个客户端接入呢? https://github.com/ray1888/Python-socket-programming 项目地址在此,使用的是 server-connect-test.pyclient-connect-test.py 作为服务器端和客户端,如果有大神提一点建议,万分感谢

3405 次点击
所在节点    Python
18 条回复
billlee
2017-06-13 22:56:11 +08:00
这个问题和 python 一点关系都没有,去看 APUE 和 UNP
a87150
2017-06-13 23:01:31 +08:00
misaka19000
2017-06-13 23:21:33 +08:00
就用简单的每个链接开一个线程就行了
noli
2017-06-14 00:13:35 +08:00
支持多个客户端并发接入根本不是靠多线程。
当然,如果你说我一简单 FTP 服务器就那么几个用户,也不是不可以用多线程来实现。
但是本质上来说是一个错误的做法,不要指望碰巧把事情做对。
noli
2017-06-14 00:21:40 +08:00
有 gevent 用 gevent, 没有 gevent 用 tornado-ftp。
用 python 的目的就是大量用库用框架解决这些问题,不然人生就苦短了。
yxwzaxns
2017-06-14 00:26:43 +08:00
好巧,我也在写
github.com/yxwzaxns/cowry
ryd994
2017-06-14 02:13:24 +08:00
看请求量吧,最简单开多线程
复杂点的用 gevent 的 monkey patch 包一下,你这个情况应该不用额外处理
用 select/epoll 才是正道
AZLisme
2017-06-14 09:08:32 +08:00
上异步吧,去看看 asyncio,如果你是用 python3
ray1888
2017-06-14 09:19:44 +08:00
@AZLisme 我用的是 python3,如果上了 asyncio 还需要上多线程吗?
ray1888
2017-06-14 09:20:54 +08:00
@noli 如果我用 Python3,gevent 和 asyncio 应该用哪一个来做协程?然后做了协程之后,还需要多开线程来处理吗?
AZLisme
2017-06-14 09:41:44 +08:00
@ray1888 一般而言上了异步就不需要多线程了。如果你 Python 3.5 +,我还是推荐 asyncio,它有对于 socket 的异步读写支持的,写起来应该很顺畅。
ray1888
2017-06-14 09:47:41 +08:00
@AZLisme 那是否就是协程和多线程多进程不能并存吗?因为还是不太懂协程和多线程对于并发的区别。我目前所知的协程,是单个线程在不同时间内进行多个任务的执行,等待 await 返回的结果,如果同一程序多线程或多进程,就是相当于可以同时处理多个请求,但是程序是线性运行
AZLisme
2017-06-14 09:56:47 +08:00
@ray1888 实际上可以并存!所以我刚才说的是「一般而言上了异步就不需要多线程了」

协程是异步编程一种方法,总的来说它不是传统的线性运行,在某一个局部代码块的层面上它是线性运行,不会中断的(所以不太需要锁)。但是整体来看,它的运行顺序是不确定的。

更加具体的来说,这个线程上会运行一个 EventLoop,然后选择代码块执行;某一个代码块执行到某一个地方,会主动放弃自己的执行权( yield 或 await )保存住状态,直到指定的事件被触发。这个执行权必须是主动放弃的,EventLoop 不会强制中断。放弃执行权之后,EventLoop 就会挑选下一个可以被执行的块来执行,或者有被监听的的事件发生,就会通知之前主动中断的协程继续执行。
noli
2017-06-14 10:25:15 +08:00
@ray1888

通常而言,asyncio 和 gevent 只选一个。
我也没试过混搭,两个事件循环一起用,应该会有诡异的 bug。

等你用这两者其中一个之后遇到瓶颈再考虑多线程吧。
我的观察是,你还要学习一下才能驾驭多线程吧。
ray1888
2017-06-14 22:28:25 +08:00
@noli 大神有好的 ASYNCIO 的模块教程或者项目推荐给我看吗?我看廖雪峰那个教程还是有点不太懂
noli
2017-06-15 01:59:09 +08:00
@ray1888

我也不知道什么样的教程是我懂你也懂的。
所以哪里不懂你就开帖问,请用心努力吧。
ray1888
2017-06-15 20:02:30 +08:00
@noli 你好
ray1888
2017-06-15 20:03:39 +08:00
@noli 为什么我这段代码还是会报错,他说我并没有协程,但是我不知道问题在哪个地方
import socket
import asyncio

def waiting(sock):
sock.listen(5)
sock_acc, addr = sock.accept()
return sock_acc

async def sendhello(sendsock):
sendsock.send(b'100')
remote = sendsock.getsockname()
print("{} is connect".format(remote[0]))

async def createsock():
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', 8999))
sock_acc = waiting(sock)
await sendhello(sock_acc)


if __name__ == "__main__":
loop = asyncio.get_event_loop()
#task = [createsock() for i in range(5)]
#loop.run_until_complete(task)
task = [createsock(), createsock()]
loop.run_until_complete(task)
loop.close()

报错是这样的
sys:1: RuntimeWarning: coroutine 'createsock' was never awaited

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

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

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

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

© 2021 V2EX