多进程&多线程
服务端:多进程和多线程的开启方式相同。
缺点:<1> 由于Cpython的GIL,导致同一时间无法运行多个线程;<2> 不可能无限开进进程或线程
解决办法:多进程、concurrent.futures.ProcessPoolExecutor、线程池
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
import socket
from multiprocessing import Process
from threading import Thread
class MyTcpServer:
def __init__( self , ip, port):
self .ip = ip
self .port = port
self .server = socket.socket()
self .server.bind(( self .ip, self .port))
self .server.listen( 5 )
def wait_accept( self ):
conn, addr = self .server.accept()
return conn, addr
def handle_request( self , conn):
while 1 :
try :
data = conn.recv( 1024 )
if not data: break
conn.send(data.upper())
except Exception as e:
print (e)
break
conn.close()
if __name__ = = '__main__' :
server = MyTcpServer( '127.0.0.1' , 8888 )
while 1 :
conn, addr = server.wait_accept()
p = Process(target = server.handle_request, args = (conn, )) # 创建一个进程
p.start() # 告诉操作提供,开启这个进程
|
进程池&线程池
异步提交任务,支持异步接收返回结果(submit返回一个futures对象,调用add_done_callback方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
import socket
from concurrent.futures import ProcessPoolExecutor
# from concurrent.futures import ThreadPoolExecutor
class MyTcpServer:
def __init__( self , ip, port):
self .ip = ip
self .port = port
self .server = socket.socket()
self .server.bind(( self .ip, self .port))
self .server.listen( 5 )
def wait_accept( self ):
conn, addr = self .server.accept()
return conn, addr
def handle_request( self , conn):
while 1 :
try :
data = conn.recv( 1024 )
if not data: break
conn.send(data.upper())
except Exception as e:
print (e)
break
conn.close()
if __name__ = = '__main__' :
server = MyTcpServer( '127.0.0.1' , 8888 )
pool = ProcessPoolExecutor( 5 ) # 5个进程一直服务
while 1 :
conn, addr = server.wait_accept()
pool.submit(server.handle_request, conn) # 异步提交任务
|
socketserver
优点:简化socket服务端创建流程。
提供服务端串行和并发两种服务模式(TCPServer,ThreadingTCPServer)
缺点:windows上无法使用多进程实现并发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import socketserver
class MyTcpHandler(socketserver.BaseRequestHandler):
def handle( self ): # 通信循环
while 1 :
try :
data = self .request.recv( 1024 )
if not data: break
self .request.send(data.upper())
except Exception as e:
print (e)
break
self .request.close()
if __name__ = = '__main__' :
ip_port = '127.0.0.1' , 8888
server = socketserver.ThreadingTCPServer(ip_port, MyTcpHandler) # 异步处理
server.serve_forever() # 连接循环
|
协程
优点:单线程内实现并发,代码级别模拟IO切换,提高程序运行效率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
from gevent import spawn, monkey;monkey.patch_all() # 猴子补丁,补丁:常规IO
import socket
class MyTcpServer:
def __init__( self , ip, port, my_spawn):
self .ip = ip
self .port = port
self .server = socket.socket()
self .server.bind(( self .ip, self .port))
self .server.listen( 5 )
self .spawn = my_spawn # 保存spawn本地
def wait_accept( self ):
while 1 :
conn, addr = self .server.accept()
self .spawn( self .handle_request, conn) # 检测 handle_request的io
def handle_request( self , conn):
while 1 :
try :
data = conn.recv( 1024 )
if not data: break
conn.send(data.upper())
except Exception as e:
print (e)
break
conn.close()
if __name__ = = '__main__' :
server = MyTcpServer( '127.0.0.1' , 8888 , spawn)
g1 = server.spawn(server.wait_accept) # 检测wait_accept的io
g1.join() # 等待g1运行结束,即一直在循环检测io
|
以上就是python 实现socket服务端并发的四种方式的详细内容,更多关于python socket服务端并发的资料请关注服务器之家其它相关文章!
原文链接:https://www.cnblogs.com/the3times/p/12821579.html