07.网络编程-2.UDP

1、udp介绍

UDP --- 用户数据报协议, 是一个无连接的简单的面向数据报的传输层协议。 UDP不提供可靠性, 它只是把应用程序传给IP层的数据报发送出去, 但是并不能保证它们能到达目的地。 由于UDP在传输数据报前不用在客户和服务器之间建立一个连接, 且没有超时重发等机制, 故而传输速度很快。
UDP是一种面向无连接的协议, 每个数据报都是一个独立的信息, 包括完整的源地址或目的地址, 它在网络上以任何可能的路径传往目的地, 因此能否到达目的地, 到达目的地的时间以及内容的正确性都是不能被保证的。

【 适用情况】
UDP是面向消息的协议, 通信时不需要建立连接, 数据的传输自然是不可靠的, UDP一般用于多点通信和实时的数据业务, 比如:

  • 语音广播
  • 视频
  • QQ
  • TFTP(简单文件传送)
  • SNMP( 简单网络管理协议)
  • RIP( 路由信息协议, 如报告股票市场, 航空信息)
  • DNS(域名解释)

UDP操作简单, 而且仅需要较少的监护, 因此通常用于局域网高可靠性的分散系统中client/server应用程序。 例如视频会议系统, 并不要求音频视频数据绝对的正确, 只要保证连贯性就可以了, 这种情况下显然使用UDP会更合理一些。

image

2、udp网络程序-发送数据

创建一个udp客户端程序的流程是简单, 具体步骤如下:

  1. 创建客户端套接字
  2. 发送/接收数据
  3. 关闭套接字
from socket import *
#1.创建套接字
udpSocket = socket(AF_INET,SOCK_DGRAM)
#2.准备接收方的地址
sendAddr = ('192.168.1.103',7777)
#3.从键盘获取数据
sendData = input('请输入要发送的数据:')
#4发送数据到指定的电脑上
udpSocket.sendto(sendData.encoding('utf-8'),sendAddr)
#5.关闭套接字
udpSocket.ckose()

3、udp网络程序-接收数据

from socket import *
#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2. 准备接收方的地址
sendAddr = ('192.168.1.103', 7777)
#3. 从键盘获取数据
sendData = input("请输入要发送的数据:")
#4. 发送数据到指定的电脑上
udpSocket.sendto(sendData.encoding('utf-8'), sendAddr)
#5. 等待接收对方发送的数据
recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数
#6. 显示对方发送的数据
print(recvData)
#7. 关闭套接字
udpSocket.close()

4、udp网络程序-端口问题

重新运行多次脚本端口会发生改变,原因在于, 当重新运行时, 如果没有确定到底用哪个, 系统默认会随机分配

端口唯一标识这个程序,如果其他电脑上的网络程序如果想要向此程序发送数据, 那么就需要向这个端口标识的程序发送即可

5、udp绑定信息

如果需要做成一个服务器端的程序的话,端口号是需要绑定的

from socket import *
#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2. 绑定本地的相关信息, 如果一个网络程序不绑定, 则系统会随机分配
bindAddr = ('', 7788) # ip地址和端口号, ip一般不用写, 表示本机的任何一个ip
udpSocket.bind(bindAddr)
#3. 等待接收对方发送的数据
# 返回一个元组(数据字节,(发送放的ip,port))
recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最⼤字节数
#4. 处理数据
msg = recvData[0].decode('gbk')
ip = recvData[1][0]
port = recvData[1][1]
#5. 显示接收到的数据
myMsg = '【Receive from %s : %s】:%s'%(ip,port,msg)
print(myMsg)
#6. 关闭sockcet
myUDP.close()

总结

一个udp网络程序, 可以不绑定, 此时操作系统会随机进行分配一个端口, 如果重新运行次程序端口可能会发生变化
一个udp网络程序, 也可以绑定信息( ip地址, 端口号) , 如果绑定成功, 那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的

6、udp网络通信过程

image

7、udp应用: echo服务器

Echo服务是一种非常有用的用于调试和检测的工具。这个协议的作用也十分简单,接收到什么原封发回就是了。

from socket import *
#1.创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2.绑定本地的相关信息
bindAddr = ('', 7777) #ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddr)
num = 1
while True:
    #3.等待接收对方发送的数据
    recvData = udpSocket.recvfrom(1024) #1024表示本次接收的最大字节数
    #4.将接收到的数据再发送给对方
    udpSocket.sendto(recvData[0], recvData[1])
    #recvData是一个元组,[0]是元组中的第一个元素,存的是接收到的消息,
    #[1]是第二个元素,消息的来源,即发送方的IP地址和端口号
    
    #5. 统计信息
    print('已经将接收到的第%d个数据返回给对方,内容为:%s'%(num,recvData[0]))
    num+=1

#6. 关闭套接字
udpSocket.close()

8、udp应用: 聊天室

from socket import *
from time import ctime
#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2. 绑定本地的相关信息
bindAddr = ('', 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddr)
while True:
    #3. 等待接收对方发送的数据
    recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数
    #4. 打印信息
    print('【 %s】 %s:%s'%(ctime(),recvData[1],recvData[0]))

#5. 关闭套接字
udpSocket.close()

==强势插入——基于udp协议多线程接收数据并回复数据==

from socket import socket,AF_INET,SOCK_STREAM,SOCK_DGRAM
from threading import Thread
from time import sleep

class MyThread(Thread):
    def __init__(self,udpSocket,recvData,recvAddress):
        self.recvData = recvData
        self.recvAddress = recvAddress
        self.udpSocket = udpSocket
        Thread.__init__(self)

    def run(self):
        sendData = self.recvData.decode('gbk') + '--收到了\n'
        self.udpSocket.sendto(sendData.encode('gbk'),self.recvAddress)

#1. 创建基于UDP协议的socket对象
myUDP = socket(AF_INET,SOCK_DGRAM)
#2. 监听指定的端口号
myUDP.bind(('',8888))
while True:
    #3. 接收数据,地址
    print('等待接收中......')
    #myUDP.recvfrom(1024)得到的是一个(数据,(ip,port))
    recvData,recvAddress = myUDP.recvfrom(1024)
    #4. 回复
    MyThread(myUDP,recvData,recvAddress).start()

#5. 关闭sockcet
myUDP.close()

9、udp总结

  1. udp是TCP/IP协议族中的一种协议能够完成不同机器上的程序间的数据通信
  2. udp服务器、 客户端
    udp的服务器和客户端的区分: 往往是通过请求服务 和 提供服务来进行区分
    请求服务的一方称为: 客户端
    提供服务的一方称为: 服务器
  3. udp绑定问题
    一般情况下, 服务器端, 需要绑定端口, 目的是为了让其他的客户端能够正确发送到此进程
    客户端, 一般不需要绑定, 而是让操作系统随机分配, 这样就不会因为需要绑定的端口被占用而导致程序无法运行的情况

10、给飞秋发信息

应用程序可以在通用的tcp/ip协议基础上,加上自己的判断,组成新的应用层协议。

比如飞秋,使用的是udp协议,在此基础上包装成了IPMSG协议。

格式:

  • 版本号:包编号:发送者姓名:发送者机器名:命令字:消息
  • 1:12323434:帅哥一枚:奇酷的电脑:32:大叫好,我是一个名大帅哥
  • 注:现行的IPMSG协议的版本是1
import socket

#创建socket对象
udpSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#目的地
destAdress = ('192.168.11.74',2425)
#消息内容
sendMsg = input('>>')
#编码
sendMsg = sendMsg.encode('gbk')
#发送
udpSocket.sendto(sendMsg,destAdress)

#关闭socket对象
udpSocket.close()
print('over......')

12、udp给飞秋广播发消息(群发)

from socket import *

#创建socket对象
myUDP = socket(AF_INET,SOCK_DGRAM)
#设置可以向广播地址发消息
myUDP.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
#目的地
destAdress = ('<broadcast>',2425)
#消息内容
sendMsg = input('>>')
#编码
sendMsg = sendMsg.encode('gbk')
#发送
myUDP.sendto(sendMsg,destAdress)

#关闭socket对象
myUDP.close()
print('over......')

13、模拟QQ

from threading import Thread
from socket import *


# 1. 收数据,然后打印
def recvData():
    while True:
        recvInfo = udpSocket.recvfrom(1024)
        print(">>%s:%s" % (str(recvInfo[1]), recvInfo[0]))


# 2. 检测键盘,发数据
def sendData():
    while True:
        sendInfo = input("<<")
        udpSocket.sendto(sendInfo.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))

    tr = Thread(target=recvData)
    ts = Thread(target=sendData)

    tr.start()
    ts.start()

    # tr.join()
    # ts.join()


if __name__ == "__main__":
    main()

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,252评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,886评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,814评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,869评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,888评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,475评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,010评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,924评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,469评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,552评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,680评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,362评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,037评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,519评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,621评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,099评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,691评论 2 361

推荐阅读更多精彩内容

  • 网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编...
    程序员欧阳阅读 2,017评论 1 37
  • 计算机网络概述 网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输。 按照计算机网络的定义,通过一定...
    蛋炒饭_By阅读 1,231评论 0 10
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,711评论 18 139
  • 11.1 引言 UDP是一个简单的面向数据报的运输层协议:进程的每个输出操作都正好产生一个UDP数据报,并组装成一...
    张芳涛阅读 2,821评论 1 6
  • 1.这篇文章不是本人原创的,只是个人为了对这部分知识做一个整理和系统的输出而编辑成的,在此郑重地向本文所引用文章的...
    SOMCENT阅读 13,077评论 6 174