python学习笔记 day31 基于UDP的socket连接
1. 简单版本---同一主机的不同进程之间通信
# server.py import socket sk=socket.socket(type=socket.SOCK_DGRAM) sk.bind(('127.0.0.1',8080)) msg,addr=sk.recvfrom(1024) # 基于UDP的socket连接服务端只能先接收,而且使用recvfrom()得到元组,分别是客户端发来的消息以及客户端的地址 print(msg.decode('utf-8')) sk.sendto(bytes('hello,我是服务端发来的消息'.encode('utf-8')),addr) # UDP协议的socket 服务端给客户端发送消息时还需要带上客户端的地址 sk.close()
# client.py import socket sk=socket.socket(type=socket.SOCK_DGRAM) id_port=('127.0.0.1',8080) # 客户端需要指定所要请求连接的服务器 sk.sendto(bytes('你好服务器,我是客户端发来的消息'.encode('utf-8')),id_port) msg,addr=sk.recvfrom(1024) # 客户端收到服务器的消息以及服务器的地址(其实这里的addr也就是id_port) print(msg.decode('utf-8')) sk.close()
2. 同一主机的两个不同进程之间的实时通信
# server.py import socket sk=socket.socket(type=socket.SOCK_DGRAM) # 创建一个UDP的socket对象 sk.bind(('127.0.0.1',8080)) # 绑定一个IP地址和端口号 while True: msg,addr=sk.recvfrom(1024) # 接收客户端发来的消息和客户端的地址 print(msg.decode('utf-8')) info=input(">>>") sk.sendto(info.encode('utf-8'),addr) # 给客户端发送消息时除了要写发送的消息还需要客户端的地址 sk.close()
# client.py import socket sk=socket.socket(type=socket.SOCK_DGRAM) id_port=('127.0.0.1',8080) while True: info=input(">>>") sk.sendto(bytes(info.encode('utf-8')),id_port) msg,addr=sk.recvfrom(1024) print(msg.decode('utf-8')) sk.close()
运行结果:
3. 基于UDP实现QQ版尬聊
之前基于TCP的长连接意思是在同一时间只能跟一个客户端聊天,但是当跟一个客户端的连接断开时,可以继续跟其他客户端建立连接,互相聊天;
但是基于UDP的服务器可以和多个客户端同时聊天;
# server.py import socket sk=socket.socket(type=socket.SOCK_DGRAM) sk.bind(('127.0.0.1',8080)) while True: msg,addr=sk.recvfrom(1024) print(addr) # 可以查看是哪一个客户端(recvfrom()不仅得到客户端发来的消息,还有客户端的地址) print(msg.decode('utf-8')) info=input(">>>") sk.sendto(bytes(info.encode('utf-8')),addr) sk.close()
# client.py import socket sk=socket.socket(type=socket.SOCK_DGRAM) id_port=('127.0.0.1',8080) while True: info=input(">>>") info = ("\033[44m来自客户端1的消息:%s\033[0m" %info).encode('utf-8') # 客户端给服务器发送消息时加上一些附属信息以及颜色,便于多个客户端之间的区分 sk.sendto(info,id_port) msg,addr=sk.recvfrom(1024) print(msg.decode('utf-8')) sk.close()
# client2.py import socket sk=socket.socket(type=socket.SOCK_DGRAM) id_port=('127.0.0.1',8080) while True: info=input(">>>") info=("\033[35m来自客户端2号的消息:%s\033[0m"%info).encode('utf-8') sk.sendto(info,id_port) msg,addr=sk.recvfrom(1024) print(msg.decode('utf-8')) sk.close()
运行结果:
4.作业
server端提供服务,接受信息(客户端发来的时间的格式),将时间转化为接收到的格式再发给客户端;
client端,给服务端发送自己想要的世间的格式,然后接收到服务端处理过的时间的格式;
# server.py import socket import time import pickle sk = socket.socket(type=socket.SOCK_DGRAM) sk.bind(('127.0.0.1', 8080)) while True: msg, addr = sk.recvfrom(1024) msg=msg.decode("utf-8") print("接收到%s发来的格式为:%s" % (addr, msg)) info = time.strftime(msg, time.localtime()) # 将接收到的格式转化为格式化时间 info_str=pickle.dumps(info) # 把格式化时间转化为字符串,以便进行传输 sk.sendto(info_str, addr) sk.close()
# client1.py import time import pickle import socket sk=socket.socket(type=socket.SOCK_DGRAM) id_port=("127.0.0.1",8080) while True: format=input(">>>") sk.sendto(format.encode('utf-8'),id_port) msg_str,addr=sk.recvfrom(1024) msg=pickle.loads(msg_str) print(msg) sk.close()
# client2.py import socket import time import pickle sk=socket.socket(type=socket.SOCK_DGRAM) id_port=('127.0.0.1',8080) while True: format=input(">>>") sk.sendto(bytes(format.encode('utf-8')),id_port) msg_str,addr=sk.recvfrom(1024) msg=pickle.loads(msg_str) print(msg) sk.close()
运行结果:
这里需要注意的就是 网络传输都需要转化为bytes类型的;而且时间格式这种非字符串类型的需要借助pickle序列化为字符串类型,然后再loads回原来的格式;
关于encode 和 decode 前者是针对中文字符做的处理,先编码 然后转为bytes类型(如果本身是bytes类型就不要使用encode),后者是对bytes类型的数据转为可以显示的格式(如果本身是非bytesl类型则不可以使用)
talk is cheap,show me the code