這程式主要是用socketserver監聽2個埠,一個9999,一個10000
設計是不管哪個埠的連接,都放到類屬性conn_pool中保存起來
程式會將9999埠的連接,收到的資料,發送給10000埠的連接。將10000埠的連接,收到的資料,發送給9999埠的連接。
現在的問題是,類屬性conn_pool只能保存同埠的連接進去。如當10000、9999埠各有1個連接,但在def setup(self):回顯出來。print(MySelfServer.conn_pool.qsize())都是1。(正確應該是2的)問題出在哪呢?
# 創建服務器用到的模塊
import socketserver
from multiprocessing import Process
from queue import Queue
# https://www.cnpython.com/qa/66814
# http://www.cppcns.com/jiaoben/python/255861.html
# 第一步創建一個自己的server類,繼承BaseRequestHandler類
class MySelfServer(socketserver.BaseRequestHandler):
conn_pool = None
def __init__(self, conn_pool):
MySelfServer.conn_pool = conn_pool
def __call__(self, request, client_address, server):
h = MySelfServer(MySelfServer.conn_pool)
socketserver.BaseRequestHandler.__init__(h, request, client_address, server)
def setup(self):
self.request.sendall("Successfully connected to the server!".encode(encoding='utf-8'))
# self.request 相當于一個conn
# 加入連接池
print(id(self.request))
MySelfServer.conn_pool.put(self.request)
print(MySelfServer.conn_pool.qsize())
def finish(self):
print("This client is cleared")
def remove(self):
print("A client is offline")
MySelfServer.conn_pool.get(self.request)
# 重寫BaseRequestHandler類中的handle方法,直接寫在自己創建的類中就可以了
def handle(self): # 里面的內容為服務器端跟客戶端的所有互動
try:
while True:
# 接收資料
self.data = str(self.request.recv(1024).strip(), encoding='utf-8')
if len(self.data) == 0:
continue
# 列印客戶端ip地址和發送來的資料,這里可能會問為什么會有self.client_address這個引數,這個在父類建構式中
print(f'{self.client_address[0]}發送資訊過來了,內容為:{self.data}')
for i in MySelfServer.conn_pool:
# 將內容發送到連接本埠的所有連接,但當前連接除外,因為是它發的。有點像聊天室
if i != self.request and self.request.getsockname()[1] == i.getsockname()[1]:
i.sendall(bytes(self.data, encoding='utf-8'))
except Exception as e:
print(e)
print(self.client_address, "連接斷開")
finally:
self.request.close()
if __name__ == "__main__":
HOST = "0.0.0.0"
PORT_1 = 9999
PORT_2 = 10000
server1 = None
server2 = None
# 連接池
# 隊長是執行緒安全的,自帶鎖
g_conn_pool = Queue()
# 允許服務器重新系結一個之前使用過的埠號。
socketserver.ThreadingTCPServer.allow_reuse_address = True
# 第二步實體化四個類其中之一并傳入服務器地址和上面自己創建的服務器類,這里自己實體化的TCPServer
server1 = socketserver.ThreadingTCPServer((HOST, PORT_1), MySelfServer(g_conn_pool))
server2 = socketserver.ThreadingTCPServer((HOST, PORT_2), MySelfServer(g_conn_pool))
# 允許重用地址
server1.allow_reuse_address = True
server2.allow_reuse_address = True
p = Process(target=server2.serve_forever, args=())
p.start()
# server1需放在p.start后啟動不然會阻塞行程,server2無法啟動
server1.serve_forever()
# 主執行緒等待p執行緒的結束才退出程式
p.join()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/192925.html
上一篇:MIPS寫斐波那契數列,求助!!非遞回的和遞回都需要
下一篇:商品比價爬蟲
