1. 程式人生 > >socketserver 和 事件Event

socketserver 和 事件Event

socketserver
處理socket服務端
# 服務端TCP:
import socketserver
from threading import current_thread
# fork linux 下一個程序介面 windows沒有這介面

# 用於處理請求的類
class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
print(self)
print(self.server) # 獲取封裝的伺服器物件
print(self.client_address) # 客戶端地址
print(self.request) # 獲取客戶端的socket物件
print(current_thread())
while True:
data = self.request.recv(1024)
print(data.decode("utf-8"))
self.request.send(data.upper())
server=socketserver.ThreadingTCPServer(("127.0.0.1",9014),MyHandler,True)# 是否繫結 預設為True
server.serve_forever()

#客戶端TCP:
import socket
client=socket.socket()
client.connect(("127.0.0.1",9014))
while True:
data=input(">>:")
client.send(data.encode("utf-8"))
dic=client.recv(1034)
print(dic.decode("utf-8"))


# 服務端UDP:
import socketserver
from threading import current_thread
# fork linux 下一個程序介面 windows沒有這介面

# 用於處理請求的類
class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
print(self)
print(self.server) # 獲取封裝的伺服器物件
print(self.client_address) # 客戶端地址
print(self.request) # 獲取客戶端的socket物件,在udp中會自動獲取客戶端資料+客戶端物件
print(current_thread())
while True:
data = self.request[0]
print(data.decode("utf-8"))
self.request[1].sendto(data.upper(),self.client_address)
break
server=socketserver.ThreadingUDPServer(("127.0.0.1",9014),MyHandler,True)# 是否繫結 預設為True
server.serve_forever()


客戶端UDP:
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# client.connect()
addr=("127.0.0.1",9014)
while True:
data=input(">>:")
client.sendto(data.encode("utf-8"),addr)
dic=client.recvfrom(1024)[0]
print(dic.decode("utf-8"))


#ThreadingUDPServer 在初始化的時候建立了socket物件
#serve_forever() 將socket註冊到select(多路複用)
#select中返回一個ready 如果為True則可以處理 _handle_request_noblock 內部建立了MyHandler

#使用了socket OOP 多執行緒
#在正常開發中

#使用時的區別:
#ThreadingTCPServer
#handle 在連線成功時執行
#self.request 是客戶端的socket物件

#ThreadingUDPServer
#handle 接受到資料執行時執行
#self.request 資料和伺服器端的socket物件




Event 多執行緒知識點
事件是什麼? 某件事情發生的訊號
用來做什麼? 線上程間通訊 然而執行緒間本來就可以相互通訊
作用就只剩下簡化程式碼了

執行緒間通訊的例子
伺服器啟動需要五秒
客戶端啟動後連線伺服器
去連線伺服器必須保證伺服器已經開啟成功了

是否啟動完成就是要通訊的內容

注意 Event執行緒通訊 僅僅用於簡單的條件判斷 說白就是代替bool型別 和if判斷類似
set() 將狀態修改為True
wati() 等待狀態為True才能繼續執行

舉例:
實現相同效果的程式碼對比:
import time
from threading import Thread,Event #事件
event=Event()
# boot=False
def server_task():
global boot
print("正在啟動....")
time.sleep(5)
print("啟動...成功")
event.set()
# boot=True

def client_task():
event.wait() # 一個阻塞的函式 會阻塞直到對evernt執行set函式為止
print("連線成功")
# while True:
# time.sleep(1)
# print("連線伺服器")
# if boot:
# print("連線成功")
# break
# else:
# print("連線失敗,伺服器沒有啟動")

t1=Thread(target=server_task)
t2=Thread(target=client_task)
t1.start()
t2.start()
# t1.join()
# t2.join()