UDP编程入门
Client端测试
- UDP协议不需要建立连接
- Client端
- 连接和发送
- connect方法未连接,只是占用laddr(本地地址和端口),设置raddr(远端地址和端口)并且记录
- send方法,前提必须设置好laddr和raddr
- sendto方法,未使用connect方法,自己占用laddr,设置raddr并且记录;使用connect方法,使用其提供的laddr,远端可以使用connect设置的raddr,也可以设置成其他raddr
- 接收
- recv方法,使用前提必须设置laddr
- recvfrom方法,同上;返回二元组,(Server_info,(‘ip地址’,port))
- 接收信息的同时,想知道raddr,使用recvfrom;只接收信息,使用recv
import logging
import socket
logging.basicConfig(format='%(asctime)s,%(thread)d: %(message)s',level=logging.INFO,datefmt='%Y/%m/%d %H:%M:%S')
raddr = ('127.0.0.1',9999)
class ChatClient:
def __init__(self,raddr):
self._client = socket.socket(type=socket.SOCK_DGRAM)
self._raddr = raddr
def send(self,msg:str):
self._client.sendto(msg.encode(),self._raddr))
def recv(self):
msg = self._client.recv(1024)
print(msg,*raddr)
def stop(self):
self._client.close()
c = ChatClient(raddr)
c.send('adfd')
c.recv()
while True:
data = input('>>>>>>').strip()
if data == 'quit':
c.stop()
c.send(data)
UDP - C / S 编程初步实现
Server端
import logging
import threading
import socket
logging.basicConfig(format='%(asctime)s %(thread)d %(message)s',level=logging.INFO)
class ChatServer:
def __init__(self,ip='127.0.0.1',port=9999):
self._laddr = ip,port
self._server = socket.socket(type=socket.SOCK_DGRAM)
self.clients = set()
self.event = threading.Event()
self._lock = threading.Lock()
def start(self):
self._server.bind(self._laddr)
threading.Thread(target=self.recv,name='recv').start()
def recv(self):
while not self.event.is_set():
info,raddr = self._server.recvfrom(1024)
self.clients.add(raddr)
logging.info((raddr,info))
if info == b'' or info == b'quit':
self.clients.discard(raddr)
continue
for addr in self.clients:
self._server.sendto(info,addr)
def stop(self):
with self._lock:
for c in self.clients:
self._server.sendto(b'bye',c)
self.event.set()
self._server.close()
def main():
c = ChatServer()
c.start()
while True:
data = input('>>>>').strip()
if data == 'quit':
c.stop()
break
print(threading.enumerate())
if __name__ == '__main__':
main()
Client端
import logging
import threading
import socket
logging.basicConfig(format='%(asctime)s %(thread)d %(message)s',level=logging.INFO)
class ChatServer:
def __init__(self,ip='127.0.0.1',port=9999):
self._laddr = ip,port
self._server = socket.socket(type=socket.SOCK_DGRAM)
self.clients = set()
self.event = threading.Event()
self._lock = threading.Lock()
def start(self):
self._server.bind(self._laddr)
threading.Thread(target=self.recv,name='recv').start()
def recv(self):
while not self.event.is_set():
info,raddr = self._server.recvfrom(1024)
self.clients.add(raddr)
logging.info((raddr,info))
if info == b'' or info == b'quit':
self.clients.discard(raddr)
continue
for addr in self.clients:
self._server.sendto(info,addr)
def stop(self):
with self._lock:
for c in self.clients:
self._server.sendto(b'bye',c)
self.event.set()
self._server.close()
def main():
c = ChatServer()
c.start()
while True:
data = input('>>>>').strip()
if data == 'quit':
c.stop()
break
print(threading.enumerate())
if __name__ == '__main__':
main()
增加心跳包
Server端
import logging
import threading
import socket
import datetime
logging.basicConfig(format='%(asctime)s %(thread)d %(message)s',level=logging.INFO)
class ChatServer:
def __init__(self,ip='127.0.0.1',port=9999,interval=7):
self._laddr = ip,port
self._server = socket.socket(type=socket.SOCK_DGRAM)
self.clients = {}
self.event = threading.Event()
self._lock = threading.Lock()
self.interval = interval
def start(self):
self._server.bind(self._laddr)
threading.Thread(target=self.recv,name='recv').start()
def recv(self):
c_remove = set()
while not self.event.is_set():
try:
info,raddr = self._server.recvfrom(1024)
except Exception as e:
logging.info(e)
else:
current = datetime.datetime.now().timestamp()
if info.strip() == b'^_^':
self.clients[raddr] = current
continue
if info == b'' or info == b'quit':
self.clients.pop(raddr)
continue
logging.info((raddr,info))
self.clients[raddr] = current
for addr,stamp in self.clients.items():
if current - stamp > self.interval:
c_remove.add(addr)
self._server.sendto(info,addr)
for c in c_remove:
print(c_remove)
self.clients.pop(c)
c_remove.clear()
def stop(self):
self.event.set()
self._server.close()
def main():
c = ChatServer()
c.start()
while True:
data = input('>>>>').strip()
if data == 'quit':
c.stop()
break
print(c.clients)
print(threading.enumerate())
if __name__ == '__main__':
main()
Client端
import logging
import socket
import threading
logging.basicConfig(format='%(asctime)s,%(thread)d: %(message)s',level=logging.INFO,datefmt='%Y/%m/%d %H:%M:%S')
raddr = ('127.0.0.1',9999)
class ChatClient:
def __init__(self,raddr):
self._client = socket.socket(type=socket.SOCK_DGRAM)
self._raddr = raddr
self.event = threading.Event()
def start(self):
self._client.connect(self._raddr)
threading.Thread(target=self.heartbeat,name='heartbeat',daemon=True).start()
threading.Thread(target=self.recv,name='recv').start()
def heartbeat(self):
while not self.event.wait(3):
self.send('^_^')
def send(self,msg:str,raddr=None):
if raddr == None:
raddr = self._raddr
self._client.sendto(msg.encode(),raddr)
def recv(self):
while not self.event.is_set():
try:
msg = self._client.recv(1024)
except Exception as e:
logging.info(e)
self.event.set()
else:
logging.info(msg)
def stop(self):
self.event.set()
self.send('quit')
self._client.close()
def main():
c1 = ChatClient(raddr)
c1.start()
while True:
data = input('>>>>>>').strip()
if data == 'quit':
c1.stop()
break
c1.send(data)
if __name__ == '__main__':
main()