import socket
import threading
import logging
import datetime
logging.basicConfig(format='%(message)s', level=logging.INFO)
class ChatUdpServer:
def __init__(self, ip='127.0.0.1', port=9999, interval=10,):
self.sock = socket.socket(type=socket.SOCK_DGRAM)
self.addr = ip, port
self.event = threading.Event()
self.client_set = {}
self.interval = interval
def start(self):
self.sock.bind(self.addr)
threading.Thread(target=self.recv,).start()
def recv(self):
while not self.event.is_set():
try:
data, raddr_info = self.sock.recvfrom(1024)
print(self.sock, raddr_info)
except ConnectionResetError:
print('{} client is stop'.format(raddr_info))
self.client_set.pop(raddr_info)
continue
# temp_key = []
# data, raddr_info = self.sock.recvfrom(1024)
# if data.strip() == b'QAQ-TAT':
# self.client_set[raddr_info] = datetime.datetime.now().timestamp()
# continue
if data.strip() == b'exit':
self.client_set.pop(raddr_info)
continue
current_time = datetime.datetime.now().timestamp()
self.client_set[raddr_info] = current_time
logging.info((data, raddr_info))
msg = '{} send {}'.format(raddr_info, data.decode()).encode()
for addr, ts in self.client_set.items():
# if current_time - ts > self.interval:
# temp_key.append(addr)
# continue
self.sock.sendto(msg, addr)
# for i in temp_key:
# self.client_set.pop(i)
def stop(self):
self.sock.close()
def main():
cs = ChatUdpServer()
cs.start()
while True:
cmd = input('>>>')
if cmd.strip() == 'exit':
cs.stop()
break
print(cs.client_set)
if __name__ == '__main__':
main()
import socket
import threading
import logging
import random
logging.basicConfig(format='%(message)s', level=logging.INFO)
class ChatUdpClient:
def __init__(self, ip='127.0.0.1', port=9999):
self.sock = socket.socket(type=socket.SOCK_DGRAM)
self.raddr = ip, port
self.event = threading.Event()
self.randomIP = ip, random.randint(10000, 65535)
def start(self):
self.sock.bind(self.randomIP) # 尝试不连接,结果与connect()下一样。
# self.sock.connect(self.raddr)
threading.Thread(target=self.recv,).start()
def recv(self):
while not self.event.is_set():
try:
data, raddr = self.sock.recvfrom(1024)
except OSError:
logging.info('client is quit')
break
logging.info(data.decode())
def send(self, msg: str):
msg = '{}'.format(msg).encode()
self.sock.sendto(msg, self.raddr)
def stop(self):
self.sock.close()
if __name__ == '__main__':
cc = ChatUdpClient()
cc.start()
while 1:
cmd = input('{} >>>'.format(cc.randomIP))
if cmd.strip() == 'exit':
cc.send(cmd)
cc.stop()
break
cc.send(cmd)
print()语句,用来调试。 服务器端注释代码是为了加心跳包。
环境:windows7 下 Pycharm本地环境测试
1、服务器端开启
2、客户端开启两次(如果随机的端口被占用,重启)
3、client1发送数据,client2发送数据
4、非正常退出client1:点Pycharm终止键
5、client2发送数据多次。此时图示结果如下:
服务器窗口:
ConnectionResetError 异常抛出。 且多次被抛出。原因未明。作为UDP连接协议,两端理论上是无联系的。服务器端因客户端的非正常退出而报错???
客户端1窗口:
客户端2窗口:
解决方法:增加心跳机制,由心跳机制去控制删除异常掉线的客户端。