python -- 网络编程(UDP编程)

Python 网络编程 TCP/UDP 详细基础 1 基础概念 1.1 Linux Windows 命令行查看网络信息 Linux: ifconfig windows: ipconfig 开/关网卡:sudo ifconfig ###(网卡名) up/down 1.2 IP地址 IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。 IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。 IP地址即在网络中标识一台. 阅读详情


测试命令

windows 查找udp是否启动端口
> netstat -anp udp | find "9999"
> net stat -anbp udp | findstr 9999

linux下发给服务端数据
$ echo "123abc" | nc -u 127.0.0.1 9999

UDP服务端编程

UDP服务端编程流程

在这里插入图片描述

  • 创建socket对象。type=socket.Sock_DGRAM
  • 绑定IP和Port,bing()方法
  • 传输数据
    • 接受数据,socket.recvform(bufsize[flags]),获得一个二元组(string,address)
    • 发送数据,socket.sendto(string, address)发给某地址某信息
  • 释放资源
import socket

server = socket.socket(type=socket.SOCK_DGRAM)

server.bing(('0.0.0.0', 9999)) # 立即绑定一个udp端口
data = server.recv(1024) # 阻塞等待数据
data = server.recvfrom(1024) # 阻塞等待数据(value, (ip, port))
server.sendto(b'hello', ('192.168.142.1', 10000))

server.close()

UDP客户端编程流程

  • 创建socket对象。type=socket.Sock_DGRAM
  • 发送数据,socket.sendto(string, address)发给某地址某信息
  • 接受数据,socket.recvform(bufsize[flags]),获得一个二元组(string,address)
  • 释放资源
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
raddr = ('192.168.142.1', 9999)

client.connect(raddr)
client.sendto(b'hello', raddr)
client.send(b'hello')
data = client.recvfrom(1024) # 阻塞等待数据(value, (ip, port))
data = client.recv(1024) # 阻塞等待数据

client.close()
  • 注意:UDP是无连接协议,所以可以只有任何一端
    例如客户端数据发往服务端,服务端存在与否无所谓

UDP编程中bind、connect、send、sendto、recv、recvfrom方法使用

  • UDP的socket对象创建后,是没有占用本地地址和端口的
方法说明
bind方法可以指定本地地址和端口laddr,会立即占用
connect方法可以立即占用本地地址和端口laddr,填充远程地址和端口raddr
sendto方法可以立即占用本地地址和端口laddr,并把数据发往指定远端。
只有有了本地绑定端口,sendto就可以向任何远端发送数据
send方法需要和connect方法配合, 可以使用已经从本地端口把数据发往raddr指定的远端
recv方法要求一定要在占用了本地端口后,返回接受的数据
recvfrom方法要求一定要占用了本地端口后,返回接受的数据和对端地址的二元祖

练习 --UDP版群聊

UDP版群聊服务端代码

  • 服务端类的基本架构
class ChatUDPServer:
    def __init__(self, ip='127.0.0.1', port=9999):
        self.addr = (ip, port)
        self.sock = socket.socket(type=socket.SOCK_DGRAM)
        
    def start(self):
        self.sock.bind(self.addr) # 立即绑定
        self.sock.recvfrom(1024) # 阻塞接受数据
    
    def stop(self):
        self.sock.close()
  • 完整版版代码
import socket
import threading
import datetime
import logging


FORMAT = "%(asctime)s %(threadName) %(thread) %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)

class ChatUDPServer:
    def __init__(self, ip='127.0.0.1', port=9999):
        self.addr = (ip, port)
        self.sock = socket.socket(type=socket.SOCK_DGRAM)
        self.clients = set() # 记录客户端
        self.event = threading.Event()

    def start(self):
        self.sock.bind(self.addr) # 立即绑定
        # 启动线程
        threading.Thread(target=self.recv, name='recv').start()

    def recv(self):
        while not self.event.is_set():
            data , raddr = self.sock.recvfrom(1024) # 阻塞接受数据

            if data.strip() == b'quit':
                # 有可能发来的数据不在clients中
                if raddr in self.clients:
                    self.clients.remove(raddr)
                logging.info('{} leaving'.format(raddr))
                continue

            self.clients.add(raddr)

            msg = '{}. from {}:{}'.format(data.decode(), *raddr)
            logging.info(msg)
            msg = msg.encode()

            for c in self.clients:
                self.sock.sendto(msg, c) # 不保证对方能够收到

    def stop(self):
        for c in self.clients:
            self.sock.sendto(b'bye', c)
        self.sock.close()
        self.event.set()

def main():
    cs = ChatUDPServer()
    cs.start()

    while True:
        cmd = input('>>>')
        if cmd.strip() == 'quit':
            cs.stop()
            break
        logging.info(threading.enumerate())
        logging.info(cs.clients)

if __name__ == '__main__':
    main()

UDP版群聊客户端代码

import socket
import threading
import datetime
import logging


FORMAT = "%(asctime)s %(threadName) %(thread) %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)

class ChatUdpClient:
    def __init__(self, rip='127.0.0.1', rport=9999):
        self.sock = socket.socket(type=socket.SOCK_DGRAM)
        self.raddr = (rip, rport)
        self.event = threading.Event()

    def start(self):
        self.sock.connect(self.raddr) # 占用本地地址和端口,设置远端地址和端口
        threading.Thread(target=self.recv, name='recv').start()

    def recv(self):
        while not self.event.is_set():
            data , raddr = self.sock.recvfrom(1024)

            msg = '{}. from {}:{}'.format(data.decode(), *raddr)
            logging.info(msg)

    def send(self, msg:str):
        self.sock.sendto(msg.encode(), self.raddr)

    def stop(self):
        self.event.set()
        self.send('quit') # 通知服务端退出
        self.sock.close()
        
def main():
    cc1 = ChatUdpClient()
    cc2 = ChatUdpClient()
    cc1.start()
    cc2.start()
    print(cc1.sock)
    print(cc2.sock)
    
    while True:
        cmd = input('Input your words >>')
        if cmd.strip() == 'quit':
            cc1.stop()
            cc2.stop()
            break
        cc1.send(cmd)
        cc2.send(cmd)

if __name__ == '__main__':
    main()

上面的例子并不完善,如果客户端断开了,服务端不知道。每一个服务端还需要对所有客户端发送数据,包括已经断开的客户端。
问题:服务端如何知道客户端断开了呢?

代码改进

服务端代码改进

  • 增加心跳heartbeat机制或ack机制。这些机制同样可以用在TCP通信的时候
  • 心跳,就是一端定时发往另一端的信息,一般每次数据越少越好。心跳时间间隔约定好就行
  • ack即响应,一端收到另一端的消息后返回的确认信息

心跳机制

  1. 一般来说是客户端定时发往服务端的,服务端并不需要ack回复客户端,只需要记录该客户端还活着就行了
  2. 如果是服务端定时发往客户端的,一般需要客户端ack响应来表示活着,如果没有收到ack的客户端,服务端移除其信息。这种实现较为复杂,用的较少
  3. 也可以双向都发心跳的,用的更少

在服务器端代码中使用第一种心跳机制改进

import socket
import threading
import datetime
import logging


FORMAT = "%(asctime)s %(threadName) %(thread) %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)

class ChatUDPServer:
    def __init__(self, ip='127.0.0.1', port=9999, intreval=10):
        self.addr = (ip, port)
        self.sock = socket.socket(type=socket.SOCK_DGRAM)
        self.clients = {} # 记录客户端, 改为字典
        self.event = threading.Event()
        self.interval = intreval # 默认10秒,超时就要移除对应的客户端

    def start(self):
        self.sock.bind(self.addr) # 立即绑定
        # 启动线程
        threading.Thread(target=self.recv, name='recv').start()

    def recv(self):
        while not self.event.is_set():
            localset = set() # 清理超市
            data , raddr = self.sock.recvfrom(1024) # 阻塞接受数据

            current = datetime.datetime.now().timestamp() # float
            if data.strip() == b'^hb^': # 心跳信息
                self.clients[raddr] = current
                continue
            elif data.strip() == b'quit':
                # 有可能发来的数据不在clients中
                self.clients.pop(raddr, None)
                logging.info('{} leaving'.format(raddr))
                continue
            self.clients[raddr] = current

            msg = '{}. from {}:{}'.format(data.decode(), *raddr)
            logging.info(msg)
            msg = msg.encode()

            for c , stamp in self.clients.items():
                if current - stamp > self.interval:
                    localset.add(c)
                else:
                    self.sock.sendto(msg, c) # 不保证对方能够收到

            for c in localset:
                self.clients.pop(c)



    def stop(self):
        self.event.set()
        self.clients.clear()
        self.sock.close()

def main():
    cs = ChatUDPServer()
    cs.start()

    while True:
        cmd = input('>>>')
        if cmd.strip() == 'quit':
            cs.stop()
            break
        logging.info(threading.enumerate())
        logging.info(cs.clients)

if __name__ == '__main__':
    main()

客户端代码改进

增加定时发送心跳代码

import socket
import threading
import datetime
import logging

FORMAT = "%(asctime)s %(threadName) %(thread) %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)


class ChatUdpClient:
    def __init__(self, rip='127.0.0.1', rport=9999):
        self.sock = socket.socket(type=socket.SOCK_DGRAM)
        self.raddr = (rip, rport)
        self.event = threading.Event()

    def start(self):
        self.sock.connect(self.raddr)  # 占用本地地址和端口,设置远端地址和端口

        threading.Thread(target=self._sendhb, name='heartbeat', daemon=True).start()
        threading.Thread(target=self.recv, name='recv').start()

    def _sendhb(self): # 心跳
        while not self.event.wait(5):
            self.send('^hb^')

    def recv(self):
        while not self.event.is_set():
            data, raddr = self.sock.recvfrom(1024)

            msg = '{}. from {}:{}'.format(data.decode(), *raddr)
            logging.info(msg)

    def send(self, msg: str):
        self.sock.sendto(msg.encode(), self.raddr)

    def stop(self):
        self.event.set()
        self.send('quit')  # 通知服务端退出
        self.sock.close()


def main():
    cc1 = ChatUdpClient()
    cc2 = ChatUdpClient()
    cc1.start()
    cc2.start()
    print(cc1.sock)
    print(cc2.sock)

    while True:
        cmd = input('Input your words >>')
        if cmd.strip() == 'quit':
            cc1.stop()
            cc2.stop()
            break
        cc1.send(cmd)
        cc2.send(cmd)


if __name__ == '__main__':
    main()

UDP协议应用

UDP是无连接协议,它基于以下假设:

  • 网络足够好
  • 消息不会丢包
  • 包不会乱序

但是,即使再局域网,也不能保证不丢包,而且包的达到不一定有序

应用场景

  • 视频、音频传输,一般来说,丢些包,问题不大,最多丢些图像、听不清话语,可以重新发话语来解决
  • 海量采集数据,例如传感器发来的数据,丢几十、几百条数据也没有关系
  • DNS协议,数据内容小,一个包就能查询到结果,不存在乱序,丢包,重新请求解析

一般来说,UDP性能优于TCP,但是可靠性要求高的场合的还是要选择TCP协议

Python网络编程--UDP 1. UDP1.1 网络通信概述1.1.1 网络• 网络就是一种辅助双方或者多方能够连接在一起的工具 • 如果没有网络可想单机的世界是多么的孤单1.1.2 使用网络的目的就是为了联通多方然后进行通信用的,即把数据从一方传递给另外一方 前面的学习编写的程序都是单机的,即不能和其他电脑上的程序进行通信 为了让在不同的电脑上运行的软件,之间能够互相传递数据,就需要借助网络的功能总结: • 阅读详情

相关推荐

Python UDP 网络编程

Python UDP网络编程,流程和其它语言没有区别,但更简洁: #服务器端 server.py # 导入 socket、sys 模块 import socket import sys # 创建 socket 对象 serversocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 获取本地主机名 host = soc...

h a 6 6 6 c k 为 你解决复杂难题! 653

golang net包中两个函数的区别

1.func Dial(network, address string)    在网络network上连接地址address,并返回一个Conn接口2.func DialTCP(network string, laddr, raddr *TCPAddr)    DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"tcp"、"tcp4"、"tcp6";如果lad...

qaz540411484的专栏 935

【python】网络编程socket TCP UDP

互联网协议族 即通用标准协议,任何私有网络只要支持这个协议,就可以接入互联网。

weixin_38009144的博客 1518

UDP编程入门

UDP编程入门

qq_43320709的博客 517

Python网络编程实现TCP和UDP连接

Python的socket模块提供了TCP和UDP网络编程的基础。通过使用TCP或UDP协议,你可以轻松地实现不同计算机之间的通信和数据交换。在实际应用中,你应该根据你的需求选择适合的协议,例如TCP适合于需要可靠数据传输的应用,而UDP适合于实时应用或广播等。此外,为了实现更复杂的功能,你可能需要使用更高级的网络框架或库,如Twisted、Tornado等。

这家伙很懒,什么都没有留下 861

UDP网络编程简介及Python实现

UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输层协议,它提供了一种高效的数据传输方式,适用于那些对数据传输可靠性要求不高的应用场景。UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输层协议,它提供了一种高效的数据传输方式,适用于那些对数据传输可靠性要求不高的应用场景。UDP与TCP类似,都是传输层的协议,但UDP不提供可靠的数据传输,也不保证数据的顺序。UDP首部较小,只有8个字节,相比之下,TCP首部较大,有20个字节。

CodeHeroicX的博客 257

redis分布式——哨兵机制、redis集群

目录2、哨兵机制2.1 配置步骤2.2 python中使用哨兵3、redis集群4、集群redis在python中的使用 1、根据redis.conf文件复制两个配置文件 6381.conf(主库) 6380.conf(从库) 2、编辑6381.conf bing 0.0.0.0 port 6381 # 把保护模式设置为no,才能让外网访问 protected-mode no 编辑6380.conf bing 0.0.0.0 port 6380 # 把保护模式设置为no,才能让外网访问 protect

user_san的博客 309

基于python的UDP服务器代码

使用python代码编写的服务器系统,采用的是UDP协议和socket技术,调试可用。

python TCP: 例子

服务端: # -*- coding:utf-8 -*- from socket import * import sys class Tcp_Server: def __init__(self, ip, port, buff, listenNum): self.addr = (ip, port) self.buff = buff se...

https://ligo100.cn 小何博客欢迎访问。 312

【音视频处理】MP4、FLV、HLS适用范围,在线视频播放哪个更好

本期我们讨论在线点播的视频格式,对比这些视频格式的优劣以及原因 1、封装格式的作用 2、MP4 3、FLV 4、HLS

池鱼 - YiiGaa 2万+

深入解析Apollo Lattice Planner:自动驾驶轨迹规划的核心算法与实践

本文深入解析了百度Apollo自动驾驶平台中的核心轨迹规划算法——Lattice Planner。文章详细阐述了其作为车辆“即时决策者”的工作原理,通过“采样-评估”的六步流程(Frenet坐标转换、状态采样、轨迹生成、硬约束过滤、代价函数打分及决策平滑),在复杂路况下实时规划出安全、舒适、高效的行驶轨迹。该算法是自动驾驶实现智能决策与精准控制的关键技术。

weixin_29090677的博客 829

python io多路复用框架_python开发之IO多路复用

IO模型介绍在说IO模型之前先说说以下的概念:同步:提交一个任务之后要等待这个任务执行完毕异步:只管提交任务,不等待这个任务执行完毕就可以做其它的事情阻塞:例如:在socket中的这些recvfrom,recv,accept都会产生阻塞。非阻塞:除去阻塞中的都是一般都是非阻塞。基本分类:阻塞IO,非阻塞IO,IO多路复用,异步IO。对于一个network IO (这里我们以read举例),它会涉及...

weixin_39802969的博客 140

landsat8数据下载教程

下载landsat数据教程

weixin_44001203的博客 1万+

【Python】网络编程之UDP、TCP

Socket的英文原义是“孔”或“插座”,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket),socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。基本上,Socket 是任何一种计算机网络通讯中最基础的内容。

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

目标检测中回归损失函数(L1Loss,L2Loss,Smooth L1Loss,IOU,GIOU,DIOU,CIOU,EIOU,αIOU ,SIOU)

为了解决CIoU的问题,有学者在CIOU的基础上将纵横比拆开,提出了EIOU Loss,并且加入Focal聚焦优质的预测框,与CIoU相似的,EIoU是损失函数的解决方案,只用于训练。在错误率小的地方,梯度的值也应当小,反之在错误率大的地方,梯度也应当大,因为这时候我们需要对错误率小的情况进行微调,而错误率大的地方进行大刀阔斧的调整;如下图所示,三种情况IoU都相等,但看得出来他们的重合度是不一样的,左边的图回归的效果最好,右边的最差。DIoU的作者考虑到,在两个框中心点重合时,c与d的值都不变。

zyw2002的博客 6629

鱼眼双目测距实战:从OpenCV标定到SGBM匹配的完整流程解析

本文详细解析了鱼眼双目测距的完整流程,从OpenCV标定到SGBM匹配,涵盖标定、校正、匹配和测距四个关键阶段。通过实战经验分享,帮助开发者解决鱼眼镜头强畸变带来的测距挑战,提升测距精度至5%以内。特别适合机器人导航、自动驾驶和VR领域的开发者参考。

weixin_27298377的博客 123

Python网络编程之UDP协议

Python网络编程之UDP协议

weixin_66398100的博客 4270

React项目实战:用AntV G6打造可折叠组织架构图(附完整代码)

本文详细介绍了如何在React项目中使用AntV G6库构建一个功能完整的可折叠组织架构图。通过实战代码演示了从环境搭建、自定义节点、折叠状态管理到性能优化的全流程,重点解决了企业级应用中处理复杂树形数据、实现流畅交互等核心问题,并提供了可直接复用的组件代码。

weixin_29016315的博客 312

Python网络编程之UDP编程

Python网络编程之UDP编程(一起努力,咱们顶峰相见!!!)

精益求精,永无止境,永远在路上! 1884

扣子Coze智能体万字教程:从入门到精通,一文掌握AI工作流搭建

智能体 = 角色设定 + 提示词 + 变量输入一个好提示词的核心是结构、风格和复用性创建后可以一键发布成网页应用、对话助手整个过程0代码,只靠配置,人人可学,人人可用四、进阶一:理解「工作流」的威力如果你已经用扣子创建了几个简单的智能体,比如写个爆款小红书文案、生成一段短视频脚本,那恭喜你已经入门。但如果你还停留在“一个智能体 = 一段提示词”的层级,你离真正的智能体生产力革命,还差一步:学会搭建“工作流”——让多个大模型自动协同完成任务。

互联网架构师笔记 3493

024、反激变换器的短路保护设计

本文详细探讨了反激变换器短路保护的设计要点与实践经验。作者通过实际案例分析了短路时反激拓扑的电流特性,指出初级峰值电流限制是最基础的保护手段,但需配合打嗝模式使用。文章重点剖析了打嗝模式设计的三个关键陷阱:频率设定、退出条件和软启动衔接。同时强调次级侧辅助保护、变压器参数优化、环路响应协调的重要性,并比较了自恢复与锁死方案的适用场景。最后提出实测验证的四个关键点和设计经验:不盲信芯片手册、保护电路独立设计、充分留有余量、进行破坏性测试。全文以工程实践为导向,为反激电源的可靠短路保护提供了系统性解决方案。

Jack010169的博客 237

python——网络编程udp

python——网络编程udp一、基础知识二、udp聊天器 一、基础知识 1、ip地址 \qquad如果把网络通信比作是寄信的话,寄信要写上收件人的地址才能保证对方能够收到信,还要写上寄件人的地址,方便收件人知道信件来自于哪,知道回信给到哪里。ip地址就相当于寄件人或者收件人的地址,也就是说ip地址是每个通信设备接收信息的地址。 \qquadip地址有两类,一类是ipv4和ipv6。现在常用的ip...

vgrant的博客 340

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Python中的网络编程之UDP

Python中的网络编程之UDP 文章目录Python中的网络编程之UDP一、Socket编程`1.什么是客户端/服务器架构`?**`2.套接字:通信端点`**3.套接字地址:主机-端口对4.套接字类型二、常见的套接字对象方法和属性三、创建套接字四、UDP网络程序五、UDP的绑定端口问题六、UDP聊天器 一、Socket编程 1.什么是客户端/服务器架构? 服务器就是一系列硬件或软件,为一个或多个客户端(服务的用户)提供所需的“服务”。它存在唯一目的就是等待客户端的请求,并响应它们(提供服务),然后等待更多

wolfGuiDao的博客 909

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

基于Tcp和UDP的python网络编程案例详解

文章目录TCP和UDP网络编程1.通信协议介绍2.TCP协议和UDP协议3.Socket(套接字)4.TCP简单网络编程5.UDP简单网络编程 TCP和UDP网络编程 1.通信协议介绍 (1)定义:网络通信协议是一种网络通用语言,为连接不同操作系统和不同硬件体系结构的互联网络引提供通信支持,是一种网络通用语言。 (2)网络通信协议由三个要素组成。 语义,解释控制信息每个部分的意义。它规定了需要发出何种控制信息,以及完成的动作与做出什么样的响应。 语法,用户数据与控制信息的结构与格式,以及数据出现的顺序。 时

qq_44176343的博客 1272

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

掌握Python网络编程:从TCP到UDP

本文介绍了Python网络编程的基础知识,包括TCP和UDP协议的工作原理、Python中常用的网络编程库以及如何使用这些库进行网络通信。网络编程是当今软件开发中非常重要的技能之一,掌握Python网络编程将为开发者的职业生涯提供更多的机会和可能性。本文将介绍Python网络编程的基础知识,从TCP到UDP,帮助读者逐步掌握网络编程的核心技能。本文将介绍Python网络编程的基础知识,包括TCP和UDP协议的工作原理、Python中常用的网络编程库以及如何使用这些库进行网络通信。

weixin_71166183的博客 517

Python网络编程-Udp

Python网络编程-Udp25 网络编程(UDP)25.1 Udp服务器端程序25.2Udp客户端程序25.3 简单的udp通信程序示例 25 网络编程(UDP) 上一章介绍的是网络编程的Tcp网络服务,本章主要介绍Udp方式的网络编程。Udp通信方式是面向非连接的。而Tcp是面向连接的类似于打电话的通信方式,而Udp则是类似于校园或者企业机关里的广播,播放广播的不关心是否都听到了,而校园里的学生未必每个人都在听广播。这个例子就很像Udp网络通信,也是udp的缺点,数据在服务器和客户端之间的传递,不能保证

网络架构 588
上一篇: python -- 网络编程(TCP编程)
下一篇: Python --网络编程(SocketServer模块)
鹿夏
博客等级 码龄8年 24粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值