最近寫了一個socket示例,可以實(shí)現(xiàn)兩個功能:
- 一個服務(wù)端同時服務(wù)多個客戶端:采用帶返回值的多線程
2.客戶端發(fā)現(xiàn)服務(wù)端斷開后,自動重連
Server端代碼
import socket
import threading
import time
class MyThread(threading.Thread):
"""多線程有返回值時,使用該類"""
def __init__(self, func, args=()):
super(MyThread, self).__init__()
self.func = func
self.args = args
def run(self):
self.result = self.func(*self.args)
def get_result(self):
try:
return self.result
except Exception:
return None
def recv_data(sock, nonblock_mark):
if nonblock_mark:
'''非阻塞式接受信息'''
print("start to get message unblock")
try:
data = sock.recv(1024, 0x40)
except Exception as e:
print("no message recieved!!", e, "will recieve 3s later")
time.sleep(3)
data ="null"
else:
'''阻塞式接受信息'''
print("start to get message block")
try:
data = sock.recv(1024)
except Exception as e:
print("connection broken!!!", e)
data = None
return data
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) #設(shè)置端口復(fù)用
s.bind(('', 123456))
s.listen(5)
print("waiting for connection!!!")
while True:
sock, addr = s.accept()
print("receive connection from %s:%s" % addr)
while True:
t = MyThread(recv_data, args=((sock, 1)))
t.start()
t.join()
data = t.get_result()
print(data)
print("length of data:", len(data), time.time())
if data == 'exit' or not data:
print("connection from %s:%s closed" % addr)
sock.close()
break
elif data == "null":
print("receieve no data on nonblocking mode!!")
continue
s.close()
Client端代碼
# 導(dǎo)入 socket、sys 模塊
import socket
import struct
import time
def doConnect(host, port):
# 創(chuàng)建 socket 對象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
s.connect((host, port))
except Exception as e:
print("connection broken:", e, "will reconnect 3s later!!")
time.sleep(3)
else:
break
return s
# 獲取本地主機(jī)名
host = "127.0.0.1"
# 設(shè)置端口號
port = 123456
# 連接服務(wù),指定主機(jī)和端口
s = doConnect(host, port)
while True:
data = input("please input anykey to continue:")
if task_type:
# 發(fā)送消息:如果連接失敗,重連服務(wù)器,重新發(fā)送
try:
s.send(data.edcode())
except socket.error as e:
print("connection borken:", e, "\nwill reconnect 3s later")
s = doConnect(host, port)
s.send(data)
else:
continue
s.close()
當(dāng)然,這段代碼也是有缺陷的:
1.標(biāo)準(zhǔn)代碼應(yīng)該采用類的方式來寫,本人類的基礎(chǔ)比較弱,有待加強(qiáng)
2.一個服務(wù)端同時服務(wù)多個客戶端,官方推薦采用select模塊
3.客戶端的自動重連功能有缺陷:當(dāng)服務(wù)端斷開30s之內(nèi),客戶端依然認(rèn)為服務(wù)端在線,這個bug暫時沒找到解決方案
參考資料:
python-socket客戶端設(shè)置自動重連,服務(wù)端線程收發(fā)消息
Python socket 怎么判斷連接斷開
Python-select詳解(select、epoll)