面向連接的并發(fā)服務器
def main():
# 1. 創(chuàng)建socket套接字
tcp_server = socket(AF_INET, SOCK_STREAM)
# 2. 綁定IP地址和端口
tcp_server.bind(("", 8888))
# 3. 把主動模式變成被動模式 只能接收 不能發(fā)送數(shù)據(jù)
tcp_server.listen(5)
while True:
# 4. 等待客戶端連接
new_socket, client_info = tcp_server.accept()
print(f"新的客戶端來了 {client_info}")
# 5. 接收數(shù)據(jù)
raw_data = new_socket.recv(1024)
while raw_data:
print(f"收到{client_info}數(shù)據(jù): {raw_data}")
# 再次取
raw_data = new_socket.recv(1024)
# 6.關閉新套接字
new_socket.close()
if __name__ == '__main__':
main()
只能同時為一個人服務
多進程并發(fā)服務器
from socket import *
from multiprocessing import Process
def rec_data(client_info, new_socket):
"""新套接字處理數(shù)據(jù)"""
raw_data = new_socket.recv(1024)
while raw_data:
print(f"收到{client_info}數(shù)據(jù): {raw_data}")
# 再次取
raw_data = new_socket.recv(1024)
# 關閉套接字
new_socket.close()
def main():
# 1. 創(chuàng)建socket套接字
tcp_server = socket(AF_INET, SOCK_STREAM)
# 2. 綁定IP地址和端口
tcp_server.bind(("", 7777))
# 3. 把主動模式變成被動模式 只能接收 不能發(fā)送數(shù)據(jù)
tcp_server.listen(5)
while True:
# 4. 等待客戶端連接
new_socket, client_info = tcp_server.accept()
print(f"新的客戶端來了 {client_info}")
# 5. 接收數(shù)據(jù)
# rec_data(client_info, new_socket)
# 6.創(chuàng)建新的進程
p = Process(target=rec_data, args=(client_info, new_socket))
# 6.1 啟動進程
p.start()
# 6.關閉新套接字 多進程必需關閉new_socket 因為會復制出來一個新的
new_socket.close()
if __name__ == '__main__':
main()
多進程服務器代表:Apache服務器
主進程中必需關閉new_socket.close()
多線程并發(fā)服務器
from socket import *
from threading import Thread
def rec_data(client_info, new_socket):
"""新套接字處理數(shù)據(jù)"""
raw_data = new_socket.recv(1024)
while raw_data:
print(f"收到{client_info}數(shù)據(jù): {raw_data}")
# 再次取
raw_data = new_socket.recv(1024)
# 關閉套接字
new_socket.close()
def main():
# 1. 創(chuàng)建socket套接字
tcp_server = socket(AF_INET, SOCK_STREAM)
# 2. 綁定IP地址和端口
tcp_server.bind(("", 7788))
# 3. 把主動模式變成被動模式 只能接收 不能發(fā)送數(shù)據(jù)
tcp_server.listen(5)
while True:
# 4. 等待客戶端連接
new_socket, client_info = tcp_server.accept()
print(f"新的客戶端來了 {client_info}")
# 5. 接收數(shù)據(jù)
# rec_data(client_info, new_socket)
# 6.創(chuàng)建新的進程
p = Thread(target=rec_data, args=(client_info, new_socket))
# 6.1 啟動進程
p.start()
# 6.關閉新套接字
#new_socket.close()
if __name__ == '__main__':
main()
多線程代表:IIS服務器
子線程共享主線程的變量,所以主線程中不能關閉new_socket.close(),否則子線程也會斷開連接
單進程非阻塞版并發(fā)服務器
from socket import *
def main():
# 1. 創(chuàng)建socket套接字
tcp_server = socket(AF_INET, SOCK_STREAM)
# 2. 把套接字設置成非阻塞
tcp_server.setblocking(False)
# 2. 綁定IP地址和端口
tcp_server.bind(("", 6667))
# 3. 把主動模式變成被動模式 只能接收 不能發(fā)送數(shù)據(jù)
tcp_server.listen(5)
# 4. 聲明一個列表用來存新的套接字
socket_lists = []
while True:
try:
# 4. 等待客戶端連接
new_socket, client_info = tcp_server.accept()
# 4.1 設置new_socket為非阻塞
new_socket.setblocking(False)
except:
pass
else:
"""已經有人連接屋彪,取到數(shù)據(jù)了"""
# 把新的套接字往列表里扔
socket_lists.append((new_socket, client_info))
print(f"新的客戶端來了 {client_info}")
# 循環(huán)列表
for sock, client_info in socket_lists:
try:
# 讓每一個new_socket去接收數(shù)據(jù) 又阻塞了,應該在創(chuàng)建new_socket后設置新的套接字為 非阻塞
raw_data = sock.recv(1024)
except:
pass
else:
# 當客戶端斷開的時候 raw_data 就是空
if raw_data:
print(f"收到{client_info}數(shù)據(jù):{raw_data.decode('gb2312')}")
else:
# 客戶端斷了
sock.close()
# 列表移除
socket_lists.remove((sock, client_info))
if __name__ == '__main__':
main()