udp是面向无连接的通讯协议,udp数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。 udp传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内。 udp是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。udp是面向消息的协议,通信时不需要建立连接,数据的传输自然是不可靠的,udp一般用于多点通信和实时的数据业务,比如:
创建一个udp客户端程序的流程是简单,具体步骤如下:
代码如下:
#coding=utf-8
from socket import *
#1、创建socket套接字
#socket(参数1,参数2)
#参数1 = AF_INET固定的
#参数2 = SOCK_DGRAM表示udp,上篇文章中说过SOCK_STREM表示tcp
udpSocket = socket(AF_INET,SOCK_DGRAM)
#2、准备接收方的地址
sendAddress = ("192.168.100.101",8080)
#3、从键盘输入需要发送的数据
sendData = input("请输入要发送的数据:")
#4、发送数据到指定电脑
udpSocket.sendto(sendData.encode(),sendAddress)
#5、关闭socket套接字
udpSocket.close()
运行程序:
这个时候我就向我的另外一台IP地址为:192.168.100.101 端口号为8080的程序发送了“我是侯哥”这一条消息。我们借助于网络调试助手软件用于测试,网络调试助手各个平台的系统都有,大家可以自己下载使用。
说明:我的代码是在windows电脑上运行的,我的网络调试助手是在Mac电脑上运行的,如果没有两台电脑的,也可以使用虚拟机测试。
#coding=utf-8
from socket import *
#1、创建socket套接字
udpSocket = socket(AF_INET,SOCK_DGRAM)
#2、准备接收方的地址
sendAddress = ("192.168.100.101",8080)
#3、从键盘输入需要发送的数据
sendData = input("请输入要发送的数据:")
#4、发送数据到指定电脑
udpSocket.sendto(sendData.encode(),sendAddress)
#5、等待接收对方发送的数据
receiveData = udpSocket.recvfrom(1024)
#6、显示对方发送的数据
print(receiveData)
#7、关闭socket套接字
udpSocket.close()
运行程序:
会变的端口号:重新运行多次脚本,然后在“网络调试助手”中,看到的现象如下:
说明:
一般情况下,在一天电脑上运行的网络程序有很多,而各自用的端口号很多情况下不知道,为了不与其他的网络程序占用同一个端口号,往往在编程中,udp的端口号一般不绑定,但是如果需要做成一个服务器端的程序的话,是需要绑定的。就像报警电话每天都在变,想必世界就会乱了,所以一般服务性的程序,往往需要一个固定的端口号,这就是所谓的端口绑定
绑定示例
#coding=utf-8
from socket import *
#1、创建socket套接字
udpSocket = socket(AF_INET,SOCK_DGRAM)
#2、绑定相关信息,如果一个网络程序不绑定,则系统会随机分配
bindAddress = ("",7781)#ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddress)
#3、等待接收方发送消息
receiveData = udpSocket.recvfrom(1024)
#4、显示对方发送的数据
print(receiveData)
#5、关闭socket套接字
udpSocket.close()
windows电脑发送信息
mac电脑接收信息如下:
说明:
#coding=utf-8
from threading import Thread
from socket import *
#接收数据
def receiveInfo():
while True:
receiveData = udpSocket.recvfrom(1024)
print("<<%s:%s"%(str(receiveData[1]),str(receiveData[0])))
#发送数据
def sendInfo():
while True:
sendData = input("")
udpSocket.sendto(sendData.encode("gb2312"),(destIp,destPort))
udpSocket = None
destIp = ""
destPort = 0
def main():
global udpSocket
global destIp
global destPort
destIp = input("对方的IP:")
destPort = int(input("对方的Port:"))
udpSocket = socket(AF_INET,SOCK_DGRAM)
udpSocket.bind(("",4567))#这里写两个()的原因是将("",4567)当做一个整体元组使用
tr = Thread(target = receiveInfo)
ts = Thread(target = sendInfo)
tr.start()
ts.start()
tr.join()
ts.join()
if __name__ == '__main__':
main()
Mac电脑上执行程序如下:
windows电脑上运行网络调试助手如下:
从而就是实现了基于socket的udp的聊天功能。
程序基本流程:创建接收端socket ---> 创建发送到socket ---> 启动接收端socket ---> 启动发送端socket ---> 等待用户输入 ---> 接收用户输入并发送到广播 ---> 接收信息并显示。
# -*- coding:utf-8 -*-
from socket import *
from time import ctime, sleep
import threading
class ChatRoomPlus:
def __init__(self):
# 全局参数配置
self.encoding = "utf-8" # 使用的编码方式
self.broadcastPort = 7788 # 广播端口
# 创建广播接收器
self.recvSocket = socket(AF_INET, SOCK_DGRAM)
self.recvSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
self.recvSocket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
self.recvSocket.bind(('', self.broadcastPort))
# 创建广播发送器
self.sendSocket = socket(AF_INET, SOCK_DGRAM)
self.sendSocket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
# 其他
self.threads = []
def send(self):
"""发送广播"""
print("UDP发送器启动成功...")
self.sendSocket.sendto("***加入了聊天室".encode(self.encoding), ('255.255.255.255', self.broadcastPort))
while True:
sendData = input("请输入需要发送的消息:")
self.sendSocket.sendto(sendData.encode(self.encoding), ('255.255.255.255', self.broadcastPort))
# print("【%s】%s:%s" % (ctime(), "我", sendData))
sleep(1)
def recv(self):
"""接收广播"""
print("UDP接收器启动成功...")
while True:
# 接收数据格式:(data, (ip, port))
recvData = self.recvSocket.recvfrom(1024)
print("【%s】[%s : %s] : %s" % (ctime(), recvData[1][0], recvData[1][1], recvData[0].decode(self.encoding)))
sleep(1)
def start(self):
"""启动线程"""
t1 = threading.Thread(target=self.recv)
t2 = threading.Thread(target=self.send)
self.threads.append(t1)
self.threads.append(t2)
for t in self.threads:
t.setDaemon(True)
t.start()
while True:
pass
if __name__ == "__main__":
demo = ChatRoomPlus()
demo.start()
运行效果:
Mac电脑上运行
linux电脑上运行程序
windows上运行程序