UDP协议 并发编程
一.TCP半连接池原理
半连接池的工作原理
目前我们的程序是单线程 服务器要么处理通讯要么处理连接请求 无法同时进行
#服务器 import socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind(("127.0.0.1",9999)) # 不是罪大连接数 server.listen(5) while True: c,addr = server.accept while True: try: msg = c.recv(1024).decode("utf-8") if not msg: c.close() break c.send(msg.upper().encode("utf-8")) except BaseException: print("客户端异常断开") c.close() server.close() #用户端 import socket client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(("127.0.0.1",9999)) while True: data = input(">>>:") if not data:coninue client.send(data.encode("utf-8") print(msg) client.close()
二.TCP 和 UDP 发送数据是的流程
解释 为何TCP是可靠的 是因为发送数据后必须受到确认包
#服务器 import socket #创建socket对象 指定type参数为socket.SOCK_DGRAM表示使用UDP协议 server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#datagram数据报的意思 # 绑定ip和端口 server.bind(("127.0.0.1",8888)) while True: # 接受数据 返回一个元祖 数据和 发送方的地址 msg,c_adde = server.recvfrom(1024) print("收到来自%s: 说:%s"%(c_addr[0],msg.decode("utf-8"))) # 发送数据到指定ip和端口 server.sendto(msg.upper(),c_addr) #客户端 import socket client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg = input(">>>:") client.sendto(msg.encode("utf-8"),("127.0.0.1",8888)) print(data.decode("utf-8")
三.UDP聊天
与TCP代码的区别
不需要监听 不需要接收
type参数为 SOCK_DGRAM
UDP 可以同时处理多个客户端 是因为CPU处理速度快 给人感觉像同时处理
群聊
1.客户端先把数据交给服务器
2.服务器先存储对方的地址
3.把收到的数据给所有人都发一遍
#服务器 import socket server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) server.bind(("127.0.0.1",8848)) #如果客户端与服务器同一台计算机 并且有多个客户端 这些客户端ip都是相同127.0.0.1 clients = {} while True: msg,addr = server.recvfrom(1024) # 存储对方的地址: clients[addr[1]] = addr print(msg.decode("utf-8")) #循环发给所有人 for c in clients: server.sendto(msg,clients[c]) #客户端1 import socket c = coket.c=soket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg= input(">>>:") c.sendto(msg.encode("utf-8"),("127.0.0.1",8848)) msg,addr = c.recvfrom(1024) print(msg.decode("utf-8")) #客户端2 import socket c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg = input(">>>:" c.sendto(msg.encode("utf-8"),("127.0.0.1",8848)) msg,addr = c.recvfrom(1024) print(msg.decode("utf-8"))
UDP聊天2
#服务器 import socket server = socket.socket(socket.AF_INET,sccket.SOCK_DGRAM) server.bind(("127.0.0.1",8848)) clients={} while True: msg,addr = server.recvfrom(1024) clients[addr[1]] = addr print(msg.decode("utf-8")) for c in clients: server.sendto(msg,clients[c]) #发送机 import socket c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg = input(">>>:") c.sendto(msg.encode("utf-8"),("127.0.0.1",8848) #接收机 import socket c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #先随便发一条消息给服务器 让服务指导自己的地址 c.sendto("register".encode("utf-8"),("127.0.0.1",8848)) while True: msg,addr = c.recvfrom(1024) print(msg.decode("utf-8"))
6.UDP会粘包么?
#服务器 import socket server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) server.bind(("127.0.0.1",8888)) while True: msg,c_addr = server.recvfrom(512) print("收到自己%: 说:%s"%(c_addr[0],msg.decode("utf-8"))) server.sendto(msg.upper(),c_addr) #客户端 import socket client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) client.sendto("10".encode("utf-8"),("127.0.0.1"8888)) client.sendto("22".encode("utf-8"),("127.0.0.1"8888)) client.sendto("32".encode("utf-8"),("127.0.0.1"8888)) client.sendto("43".encode("utf-8"),("127.0.0.1"8888))
结论:
1.UDP 不粘包
2.缓冲区大小要足够装数据包大小 建议不要超过512
UDP的使用场景: 视频电话 语音电话 直播
DNS 域名解析服务器
做一个时间服务器 使用UDP协议 客户端请求服务器获取当前时间
#服务端 import socket import time # 创建socket对象 指定type参数为socket.SOCK_DGRAM 表示使用UDP协议 server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # datagram数据报的意思 # 绑定ip和端口 server.bind(("127.0.0.1",8889)) while True: # 接收数据 返回一个元祖 数据和 发送方的地址 msg,c_addr = server.recvfrom(1024) msg=time.strftime("%Y-%m-%d %X").encode("utf-8") print("%s 收到来自%s: 说:%s" % (time.strftime("%Y-%m-%d %X"),c_addr[0] ,msg.decode("utf-8"))) print(type(msg)) # 发送数据到指定ip和端口 server.sendto(msg.upper(),c_addr) #用户端 import socket client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # datagram数据报的意思 while True: msg = input(">>>:") client.sendto(msg.encode("utf-8"),("127.0.0.1",8889)) data,addr = client.recvfrom(1024) print(data.decode("utf-8"))