多线程并发服务器
进程是系统分配资源的最小单位,每创建一个进程都会耗费一些系统资源,当进程较多时,服务器的效率会因系统内存的减少而降低。为解决这一问题,人们考虑使用耗费资源较少的线程代替进程,搭建多线程并发服务器。
对前面的多进程并发服务器进行修改,多线程并发服务器的代码实现如下。
import socket
import threading
# 与客户端进行交互
def deal_with_client(new_socket, client_address):
while True:
recv_data = new_socket.recv(1024).decode('gb2312')
if len(recv_data) > 0:
print('待处理数据%s:%s' % (str(client_address), recv_data))
data = recv_data.upper()
new_socket.send(data.encode('gb2312'))
else:
print('客户端[%s]已关闭'%str(client_address))
break
new_socket.close()
def main():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
local_address = ('', 8082)
server_socket.bind(local_address)
server_socket.listen(5)
print('-----服务器-----')
try:
while True:
new_socket,client_address = server_socket.accept()
print('一个新的客户端到达[%s]' % str(client_address))
# 创建线程,与客户端进行交互
client = threading.Thread(target=deal_with_client,
args=(new_socket, client_address))
client.start()
finally:
server_socket.close()
if __name__ == '__main__':
main()
多线程服务器与多进程服务器基本相同,值得注意的是,多进程服务器在创建子进程后,会调用close()方法关闭服务器进程的new_socket,这是因为,在创建子进程时new_socket已被复制给了子进程,服务器进程中的new_socket不再使用;但在多线程服务器中,主线程和新线程共享new_socket,若在服务器线程中关闭new_socket,新线程将无法再使用new_socket与客户端进程交互。
与进程相比,虽然线程消耗的资源较少,但大量线程占据的内存仍相当可观,此外,线程的稳定性较差,所以多进程和多线程服务器通常只能用在规模较小、对性能要求较低的场合。