今天主題是實現并發服務器,實現方法有多種版本,先從簡單的單進程代碼實現到多進程,多線程的實現,最終引入一些高級模塊來實現并發TCP服務器。
說到TCP,想起吐槽大會有個段子提到三次握手,也只有程序猿(媛)能get。
UDP服務器數據傳輸不可靠,這里就忽略了。
>>:
簡單的單進程TCP服務器
假代碼:
#創建tcp服務器套接字
#綁定端口
#設置正常情況退出的服務器下,端口可以重用
#設置監聽,變為主動監聽
# 等待客戶端的鏈接,返回新的socket和地址
#關閉tcp服務器套接字
from socket import socket, AF_INET,SOCK_STREAM,SOL_SOCKET,SO_REUSEADDR#創建tcp服務器套接字server_socket = socket(AF_INET,SOCK_STREAM)#綁定端口server_socket.bind(("",9999))#設置正常情況退出的服務器下,端口可以重用server_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#設置監聽,變為主動監聽server_socket.listen(5)while True: # 等待客戶端的鏈接,返回新的socket和地址 new_socket,new_address = server_socket.accept() #接收數據,并且發送數據 try: while True: recv_data = new_socket.recv(1024) #當有客戶端關閉后,recv解除阻塞,并且返回長度為0 if len(recv_data) > 0: recv_content = recv_data.decode("gb2312") print("收到:%s的信息是:%s" % (str(new_address),recv_content)) new_socket.send("thank you!".encode("gb2312")) else: print("客戶端%s已經關閉" % (str(new_address))) break finally: new_socket.close() print("關閉%s客戶端" % (str(new_address)))#關閉tcp服務器套接字server_socket.close()多進程TCP服務器
from socket import socket, AF_INET,SOCK_STREAM,SOL_SOCKET,SO_REUSEADDRfrom multiprocessing import Process#在子進程中接收消息def recv_data(new_socket,new_address): while True:  recv_data = new_socket.recv(1024)  # 當有客戶端關閉后,recv解除阻塞,并且返回長度為0  if len(recv_data) > 0:   recv_content = recv_data.decode("gb2312")   print("收到:%s的信息是:%s" % (str(new_address), recv_content))   new_socket.send("thank you!".encode("gb2312"))  else:   print("客戶端%s已經關閉" % (str(new_address)))   break #關閉與客戶端的連接 print("關閉與客戶端的連接") new_socket.close()def main(): #創建tcp服務器套接字 server_socket = socket(AF_INET,SOCK_STREAM) #綁定端口 server_socket.bind(("",8888)) #設置正常情況退出的服務器下,端口可以重用 server_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #設置監聽,變為被動連接 server_socket.listen(3) try:  while True:   # 等待客戶端的鏈接,返回新的socket和地址   new_socket,new_address = server_socket.accept()   #接收數據,并且發送數據   Process(target=recv_data,args=(new_socket,new_address)).start()   #因為主進程和子進程不共享數據   #如果我們直接關閉new_socket,只是關閉主進程的new_socket,而子進程的不受影響   new_socket.close() finally:  #關閉tcp服務器套接字  server_socket.close()if __name__ == "__main__": main()            
新聞熱點
疑難解答