最近开始搞 Python 的网络编程,在写 FTP 服务器。然后基础功能都可以了(项目的目录还没优化),但是不知道怎么使可以使得多个客户端接入,怎样添加多线程或多进程才能是项目可以支持多个客户端接入呢? https://github.com/ray1888/Python-socket-programming 项目地址在此,使用的是 server-connect-test.py 和 client-connect-test.py 作为服务器端和客户端,如果有大神提一点建议,万分感谢
1
billlee 2017-06-13 22:56:11 +08:00
这个问题和 python 一点关系都没有,去看 APUE 和 UNP
|
2
a87150 2017-06-13 23:01:31 +08:00
|
3
misaka19000 2017-06-13 23:21:33 +08:00 via Android
就用简单的每个链接开一个线程就行了
|
4
noli 2017-06-14 00:13:35 +08:00
支持多个客户端并发接入根本不是靠多线程。
当然,如果你说我一简单 FTP 服务器就那么几个用户,也不是不可以用多线程来实现。 但是本质上来说是一个错误的做法,不要指望碰巧把事情做对。 |
5
noli 2017-06-14 00:21:40 +08:00
有 gevent 用 gevent, 没有 gevent 用 tornado-ftp。
用 python 的目的就是大量用库用框架解决这些问题,不然人生就苦短了。 |
6
yxwzaxns 2017-06-14 00:26:43 +08:00 via iPhone
好巧,我也在写
github.com/yxwzaxns/cowry |
7
ryd994 2017-06-14 02:13:24 +08:00 via Android
看请求量吧,最简单开多线程
复杂点的用 gevent 的 monkey patch 包一下,你这个情况应该不用额外处理 用 select/epoll 才是正道 |
8
AZLisme 2017-06-14 09:08:32 +08:00
上异步吧,去看看 asyncio,如果你是用 python3
|
10
ray1888 OP @noli 如果我用 Python3,gevent 和 asyncio 应该用哪一个来做协程?然后做了协程之后,还需要多开线程来处理吗?
|
11
AZLisme 2017-06-14 09:41:44 +08:00 1
@ray1888 一般而言上了异步就不需要多线程了。如果你 Python 3.5 +,我还是推荐 asyncio,它有对于 socket 的异步读写支持的,写起来应该很顺畅。
|
12
ray1888 OP @AZLisme 那是否就是协程和多线程多进程不能并存吗?因为还是不太懂协程和多线程对于并发的区别。我目前所知的协程,是单个线程在不同时间内进行多个任务的执行,等待 await 返回的结果,如果同一程序多线程或多进程,就是相当于可以同时处理多个请求,但是程序是线性运行
|
13
AZLisme 2017-06-14 09:56:47 +08:00
@ray1888 实际上可以并存!所以我刚才说的是「一般而言上了异步就不需要多线程了」
协程是异步编程一种方法,总的来说它不是传统的线性运行,在某一个局部代码块的层面上它是线性运行,不会中断的(所以不太需要锁)。但是整体来看,它的运行顺序是不确定的。 更加具体的来说,这个线程上会运行一个 EventLoop,然后选择代码块执行;某一个代码块执行到某一个地方,会主动放弃自己的执行权( yield 或 await )保存住状态,直到指定的事件被触发。这个执行权必须是主动放弃的,EventLoop 不会强制中断。放弃执行权之后,EventLoop 就会挑选下一个可以被执行的块来执行,或者有被监听的的事件发生,就会通知之前主动中断的协程继续执行。 |
14
noli 2017-06-14 10:25:15 +08:00
@ray1888
通常而言,asyncio 和 gevent 只选一个。 我也没试过混搭,两个事件循环一起用,应该会有诡异的 bug。 等你用这两者其中一个之后遇到瓶颈再考虑多线程吧。 我的观察是,你还要学习一下才能驾驭多线程吧。 |
18
ray1888 OP @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 |