网络程序设计

第一章

小结
1.1计算机网络发展历史

1)计算机网络技术发展的第一个里程碑以报文(Message)或分组(Packet)交换技术的出现为标志
电路交换:在电路交换方式中,通过网络节点(交换设备)在工作站之间建立专用的通信通道,即在两个工作站之间建立实际的物理连接。一旦通信线路建立,这对端点就独占该条物理通道,直至通信线路被取消。
报文交换:报文是一个带有目的端信息和控制信息的数据包。报文交换采取的是“存储—转发” 方式,不需要在通信的两个节点之间建立专用的物理线路。
分组交换:它是报文交换的一种改进,也属于存储-转发交换方式,但它不是以报文为单位,而是以长度受到限制的报文分组为单位进行传输交换的。
在这里插入图片描述
2) 计算机网络技术发展的第二个里程碑以开放式系统互联参考模型OSI/RM(Open System Interconnection/Reference Module)的出现为标志
3)计算机网络技术发展的第三个里程碑以Internet的迅速发展与推广为特征

1.2开放式系统互联参考模型(OSI/RM)

OSI参考模型(OSI/RM)的全称是开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它是由国际标准化组织ISO提出的一个网络系统互连模型。它是网络技术的基础,让网络有理可依,有据可循, 透明地处理标准和硬件的变化。
OSI模型的层次图
OSI模型各层对应的实际对象举例如下
应用层— 计算机:应用程序,如FTP,SMTP,HTTP等
表示层— 计算机:编码方式,图像编解码、URL字段编码等
会话层— 计算机:建立会话,SESSION认证、断点续传等
传输层—计算机:进程和端口等
网络层— 网络:路由器,防火墙、多层交换机等
数据链路层— 网络:网桥,交换机等
物理层— 网络:中继器、集线器、HUB等
OSI模型的成功与失败
需要指出的是:OSI/RM并非如上图那样逐层发展起来的,而是在20世纪60、70年代发展起来的不同结构层次、同名层内涵不尽相同的背景下,通过ISO有关工作组的反复研究、争论和协商的结果。因此,它既是当时能获得学术界与业界认同的网络体系结构,作为讨论网络体系结构和各种新旧网络间关系的参照,也是ISO有关工作组制定各层标准的依据。这一点也正是OSI/RM最成功之处和对计算机网络技术的最大贡献。
由于OSI系统十分复杂,加上协议中可选项太多,要实现开放式系统互联实际上并非易事。20世纪90年代由于Internet在全世界范围内得到广泛的应用,而其以TCP/IP为基础的通信协议集十分简洁,网络产品厂商和软件开发商纷纷转向,使以OSI/RM为基础的协议并未在市场上站住脚。因此,OSI有关工作的最大贡献主要体现在OSI/RM本身作为讨论网络体系结构的参考作用上。

1.3TCP/IP体系结构

在TCP/IP协议研究时,并没有提出体系结构参考模型。在1974年Kahn定义了最早的TCP/IP参考模型;20世纪80年代Leiner、 Clark等人对TCP/IP参考模型进一步的研究。TCP/IP协议一共出现了多个版本。目前我们使用的是版本4,它的网络层IP协议一般记作IPv4 ;版本6的网络层IP协议一般记作IPv6(或IPng, IP next generation);IPv6被称为下一代的IP协议。通常所提及IP协议及相关概念若没有特别说明版本,均默指IPv4。
OSI的7层结构与TCP/IP5层结构的对应关系
TCP/IP4层模型:
TCP/IP参考模型分为4层,各层的功能分别是:
(1) 应用层(application layer)
(2) 传输层(transport layer)
(3) 互连层(internet layer)
(4) 主机-网络接口层(host-to-network layer)(数据链路层、物理层合并)
OSI的7层结构与TCP/IP4层结构的对应关系--Linux
尽管TCP/IP模型在物理层和数据链路层广泛使用各种技术而未定义专用的协议,只概括地称之为“主机-网络层”。但其最下面4层结构与OSI/RM的下面4层基本是一一对应。 TCP/IP模型在体系结构上有别于OSI/RM之处在于将OSI/RM中的上面3层合成为应用层,将应用层所需的会话层和表示层功能根据需要融入应用层之中。
TCP/IP模型中的数据传输
在这里插入图片描述TCP/IP模型中的数据传输
TCP/IP协议的特点
开放的协议标准;
独立于特定的计算机硬件与操作系统;
独立于特定的网络硬件,可以运行在局域网、广域网,更适用于互连网中;
统一的网络地址分配方案,使得整个TCP/IP设备在网中都具有惟一的地址;
标准化的高层协议,可以提供多种可靠的用户服务。
与OSI/RM相比较,TCP/IP参考模型的缺陷是:
在服务、接口与协议的区别上不很清楚,一个好的软件工程应该将功能与实>现方法区分开,TCP/IP参考模型不适合于其他非TCP/IP协议簇;
TCP/IP参考模型的“主机-网络接口层”本身并不是实际的一层;

1.4客服服务器模型及原理

C/S 架构是一种典型的两层架构,其全称是Client/Server,即客户端、服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据;另一种是Socket服务器端,服务器端的程序通过Socket与客户端的程序通信。
C/S 架构也可以看做是胖客户端架构。因为客户端需要实现绝大多数的业务逻辑和界面展示。
C/S优点和缺点
优点:
1 C/S架构的界面和操作可以很丰富。
2 安全性能可以很容易保证,实现多层认证也不难。
3 由于只有一层交互,因此响应速度较快。
缺点:
1 用户群固定。由于程序需要安装才可使用,因此不适合面向一些不可知的用户。
2 维护成本高,发生一次升级,则所有客户端的程序都需要改变。
C/S——微博

B/S架构的全称为Browser/Server,即浏览器/服务器结构。主要事务逻辑在服务器端实现,B/S架构的系统无须特别安装,只有Web浏览器即可。因此也被成为瘦客户端。
必须强调的是C/S和B/S并没有本质的区别:B/S是基于特定通信协议(HTTP)的C/S架构,也就是说B/S包含在C/S中,是特殊的C/S架构。
B/S优点和缺点
优点:
1)客户端无需安装,有Web浏览器即可。
2)B/S架构可以直接放在广域网上,通过一定的权限控制实现多客户访问的目的,交互性较强。
3)B/S架构无需升级多个客户端,升级服务器即可。
缺点:
1)在跨浏览器上,B/S架构不尽如人意。
2)UI表现要达到C/S程序的程度需要花费不少精力。
3)在速度和安全性上需要花费巨大的设计成本,这是B/S架构的最大问题。
4)客户端服务器端的交互是请求-响应模式,通常需要刷新页面,这并不是客户乐意看到的。
B/S——WWW服务

1.5面向互联网的网络程序编程

作业
1.1分别简述OSI参考模型和TCP/IP模型,并阐述他们之间的对应关系

OSI模型各层对应的实际对象举例如下
应用层— 计算机:应用程序,如FTP,SMTP,HTTP等
表示层— 计算机:编码方式,图像编解码、URL字段编码等
会话层— 计算机:建立会话,SESSION认证、断点续传等
传输层—计算机:进程和端口等
网络层— 网络:路由器,防火墙、多层交换机等
数据链路层— 网络:网桥,交换机等
物理层— 网络:中继器、集线器、HUB等

TCP/IP参考模型分为4层,各层的功能分别是:
(1) 应用层(application layer)
(2) 传输层(transport layer)
(3) 互连层(internet layer)
(4) 主机-网络接口层(host-to-network layer)(数据链路层、物理层合并)

尽管TCP/IP模型在物理层和数据链路层广泛使用各种技术而未定义专用的协议,只概括地称之为“主机-网络层”。但其最下面4层结构与OSI/RM的下面4层基本是一一对应。 TCP/IP模型在体系结构上有别于OSI/RM之处在于将OSI/RM中的上面3层合成为应用层,将应用层所需的会话层和表示层功能根据需要融入应用层之中。

1.2简述数据传输的三种方式及其优缺点

电路交换:在电路交换方式中,通过网络节点(交换设备)在工作站之间建立专用的通信通道,即在两个工作站之间建立实际的物理连接。一旦通信线路建立,这对端点就独占该条物理通道,直至通信线路被取消。
报文交换:报文是一个带有目的端信息和控制信息的数据包。报文交换采取的是“存储—转发” 方式,不需要在通信的两个节点之间建立专用的物理线路。
分组交换:它是报文交换的一种改进,也属于存储-转发交换方式,但它不是以报文为单位,而是以长度受到限制的报文分组为单位进行传输交换的。

1.3简述C/S,B/S模型并分析他们的优缺点

C/S 架构是一种典型的两层架构,其全称是Client/Server,即客户端、服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据;另一种是Socket服务器端,服务器端的程序通过Socket与客户端的程序通信。
C/S 架构也可以看做是胖客户端架构。因为客户端需要实现绝大多数的业务逻辑和界面展示。
C/S优点和缺点
优点:
1 C/S架构的界面和操作可以很丰富。
2 安全性能可以很容易保证,实现多层认证也不难。
3 由于只有一层交互,因此响应速度较快。
缺点:
1 用户群固定。由于程序需要安装才可使用,因此不适合面向一些不可知的用户。
2 维护成本高,发生一次升级,则所有客户端的程序都需要改变。
C/S——微博

B/S架构的全称为Browser/Server,即浏览器/服务器结构。主要事务逻辑在服务器端实现,B/S架构的系统无须特别安装,只有Web浏览器即可。因此也被成为瘦客户端。
必须强调的是C/S和B/S并没有本质的区别:B/S是基于特定通信协议(HTTP)的C/S架构,也就是说B/S包含在C/S中,是特殊的C/S架构。
B/S优点和缺点
优点:
1)客户端无需安装,有Web浏览器即可。
2)B/S架构可以直接放在广域网上,通过一定的权限控制实现多客户访问的目的,交互性较强。
3)B/S架构无需升级多个客户端,升级服务器即可。
缺点:
1)在跨浏览器上,B/S架构不尽如人意。
2)UI表现要达到C/S程序的程度需要花费不少精力。
3)在速度和安全性上需要花费巨大的设计成本,这是B/S架构的最大问题。
4)客户端服务器端的交互是请求-响应模式,通常需要刷新页面,这并不是客户乐意看到的。
B/S——WWW服务

1.4应用程序在什么情况下建议使用UDP

应用程序只在以下情况使用UDP:
1)应用程序指明必须使用UDP;
2)应用程序协议要依靠硬件进行广播或组播
3)应用协议在可靠的环境中运行,不需要额外的可靠性处理。

1.5请阐述无状态服务器和有状态服务器概念及其特点,并介绍其优缺点。

有状态服务器具有以下特点:

  • 保存客户请求的数据(状态)
  • 服务端容易对客户状态进行管理
  • 服务端并不要求每次客户请求都携带额外的状态数据

无状态服务器具有以下特点:

  • 并不保存客户请求的数据(状态)
  • 客户在请求时需要携带额外的状态数据
  • 无状态服务器更加健壮,重启服务器不会丢失状态信息,这使得维护和扩容更加简单

第二章

小结
并发可以减少网络客户的服务等待
服务器中的并发需要编程实现
fork和execl的使用
操作系统中的并发实现:时间分片
并发的代价:上下文切换
Select调用允许单个的进程管理并发I/O
同步、异步、阻塞、非阻塞
Linux下的五种I/O模型

作业
1、并发、并行的概念及其区别

并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。这种方式我们称之为并发(Concurrent)。

并行:当系统有一个以上CPU时, 当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。

2、进程、线程的概念及其联系和区别

进程的概念:进程是表示资源分配的基本单位。它是一个执行某一个特定程序的实体,它拥有独立的地址空间、执行堆栈、文件描述符等。

线程的概念:有时被称为轻量级进程,线程是进程中执行运算的最小单位,亦即执行处理机调度的基本单位。

进程与线程的区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

3、阻塞、非阻塞、同步和异步的概念,阻塞I/O,非阻塞I/O,多路复用I/O,信号驱动I/O,异步 I/O 的原理及其示意图。

4、介绍linux fork实现的原理

父进程返回进程数
子进程返回0
错误返回负数

第三章

小结
套接字已经成为一种事实上的标准
socket函数使用PF_INET说明使用TCP/IP
其它的系统调用的使用方法
bind, listen, connect, accept, read, write, close
协议族的地址表示方式
AF_INET指明含有一个IP地址和端口号的端点地址
TCP/IP是用于定义的结构sockaddr_in
一些其他的API接口(地址转换等等)

作业
1.什么是套接字?

  1. 套接字是一个主机本地网络应用程序所创建的, 为操作系统所控制的接口 (“门”) .前面讲的系统调用!
  2. 应用进程通过这个接口,使用传输层提供的服务, 跨网络发送(或接收)消息.
    3.Client/server模式的通信接口——套接字接口.
  1. PF_INET和AF_INET分别代表什么?

使用何种服务:
SOCK_DGRAM: 数据报服务,UDP协议
SOCK_STREAM: 流服务,TCP协议
PF_INET:使用TCP/IP协议族
AF_INET: 使用TCP/IP地址结构

3.struct sockaddr和struct sockaddr_in有什么不同?

sockaddr用其余14个字节来表示sa_data,而sockaddr_in把14个字节拆分成sin_port, sin_addr和sin_zero分别表示端口、ip地址。sin_zero用来填充字节使sockaddr_in和sockaddr保持一样大小。sockaddr和sockaddr_in包含的数据都是一样的,但他们在使用上有区别:程序员不应操作sockaddr,sockaddr是给操作系统用的;程序员应使用sockaddr_in来表示地址,sockaddr_in区分了地址和端口,使用更方便。

4.accept调用完成什么功能,相关参数的说明,返回值代表什么?其他接口也要掌握,bind、listen、recv、send等接口。

int bind(int sockfd,struct sockaddr * my_addr,int addrlen)
功能:为套接字指明一个本地端点地址
TCP/IP协议使用sockaddr_in结构,包含IP地址和端口号
服务器使用它来指明熟知的端口号,然后等待连接
参数说明:
Sockfd:套接字描述符,指明创建连接的套接字
my_addr:本地地址,IP地址和端口号
addrlen :地址长度
举例:bind(sockfd, (struct sockaddr *)&address, sizeof(address));

int listen(int sockfd,int input_queue_size)
功能: 面向连接的套接字使用它将一个套接字置为被动模式,并准备接收传入连接。用于服务器,指明某个 套接字连接是被动的
参数说明:
Sockfd:套接字描述符,指明创建连接的套接字
input_queue_size:该套接字使用的队列长度,指定在请求队列中允许的最大请求数 成功返回0,出错返回-1
请将套接字设为被动模式,并允许最大请求数为20。
举例:listen(sockfd,20)

int accept(int sockfd, struct sockaddr *addr, int *addrlen);
功能:获取传入连接请求,返回新的连接的套接字描述符。
为每个新的连接请求创建了一个新的套接字,服务器只对新的连接使用该套接字,原来的监听套接字接收其他的连接请求。
新的连接上传输数据使用新的套接字,使用完毕,服务器将关闭这个套接字。 出错返回-1.
参数说明:
Sockfd:套接字描述符,指明正在监听的套接字
addr:提出连接请求的主机地址
addrlen:地址长度
举例:new_sockfd =accept(sockfd, (struct sockaddr *)&address, sizeof(address));

int connect(int sockfd,struct sockaddr *server_addr,int sockaddr_len)
功能: 同远程服务器建立主动连接,成功时返回0,若连接失败返回-1。 参数说明:
Sockfd:套接字描述符,指明创建连接的套接字
Server_addr:指明远程端点:IP地址和端口号
sockaddr_len :地址长度
举例(P49): connect(s,remaddr,remaddrlen)
UDP中调用connect内核仅仅把对端ip&port记录下来。

int send(int sockfd, const void * data, int data_len, unsigned int
flags) 功能:在TCP连接上发送数据,返回成功传送数据的长度,出错时返回-1。
send会将外发数据复制到OS内核中,也可以使用send发送面向连接的UDP报文。 参数说明: sockfd:套接字描述符
data:指向要发送数据的指针 data_len:数据长度 flags:通常为0,设置为 MSG_DONTWAIT为非阻塞
记住如果send()函数的返回值小于len
的话,则你需要再次发送剩下的数据。802.3,MTU为1492B,如果包小于1K,那么send()一般都会一次发送光的。
举例(p50):send(s,req,strlen(req),0);另外可尝试send的阻塞效果

int sendto(int sockfd, const void * data, int data_len, unsigned int
flags, struct sockaddr *remaddr,sock_len remaddr_len)
功能:基于UDP发送数据报,返回实际发送的数据长度,出错时返回-1 参数说明: sockfd:套接字描述符 data:指向要发送数据的指针
data_len:数据长度 flags:通常为0,设置为 MSG_DONTWAIT为非阻塞 remaddr:远端地址:IP地址和端口号
remaddr_len :地址长度 举例:sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr
*)&address, sizeof(address));

int recv(int sockfd, void *buf, int buf_len,unsigned int flags); 功能:
从TCP接收数据,返回实际接收的数据长度,出错时返回-1。 服务器使用其接收客户请求,客户使用它接受服务器的应答。如果没有数据,将阻塞。
如果TCP收到的数据大于(/小于)缓存的大小,只抽出能够填满缓存的足够数据(/抽出所有数据并返回它实际接收的字节数)。
也可以使用recv接收面向连接的UDP的报文,若缓存不能装下整个报文,填满缓存后剩下的数据将被丢弃。 参数说明: Sockfd:套接字描述符
Buf:指向内存块的指针 Buf_len:内存块大小,以字节为单位
flags:一般为0(MSG_WAITALL接收到指定长度数据时才返回),设置为 MSG_DONTWAIT为非阻塞
举例:recv(sockfd,buf,8192,0)

int recvfrom(int sockfd, void *buf, int buf_len,unsigned int
flags,struct sockaddr *from,sock_len *fromlen);
功能:从UDP接收数据,返回实际接收的字节数,失败时返回-1 参数说明: Sockfd:套接字描述符 buf:指向内存块的指针
buf_len:内存块大小,以字节为单位 flags:一般为0 from:远端的地址,IP地址和端口号 fromlen:远端地址长度
举例:recvfrom(sockfd,buf,8192,0,(struct sockaddr *)&address,
&sizeof(address));

close(int sockfd);    功能: 撤销套接字.
如果只有一个进程使用,立即终止连接并撤销该套接字,如果多个进程共享该套接字,将引用数减一,如果引用数降到零,则关闭连接并撤销套接字。
参数说明: Sockfd:套接字描述符 举例:close(socket_descriptor)

5.系统调用Socket( int domain, int type, int protocol)中的domain,type用来标识什么,可以有哪些值?

int Socket( int domain, int type, int protocol)
功能:创建一个新的套接字,返回套接字描述符
参数说明:
domain:域类型,指明使用的协议栈,AF_INET:IPv4协议,AF_INET6:IPv6协议,AF_LOCAL:Unix域协议,AF_ROUTE:路由套接口,AF_KEY:密钥套接口
type: 指明需要的服务类型, AF_INET地址族下如
SOCK_DGRAM: 数据报服务,UDP协议
SOCK_STREAM: 流服务,TCP协议
SOCKET_RAW:提供传输层以下的协议,例如接收和发送ICMP报文
protocol:一般都取0(由系统根据服务类型选择默认的协议)IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP
请创建一个用于TCP通信的套接字。
举例:s=socket(AF_INET,SOCK_STREAM,0)

6 .大端字节序、小端字节序的概念,理解其转换的原理。同时理解网络字节序和主机字节序的概念

大于一个字节的变量类型的表示方法有两种:
小端字节序(Little Endian,LE):在表示变量的内存地址的起始地址存放低字节,高字节顺序存放;
大端字节序(Big Endian,BE):在表示变量的内存地址的起始地址存放高字节,低字节顺序存放。

7.说明不精确指明协议软件接口的优缺点?

第四章

作业
1、请结合图示描述TCP客服-服务器模型实现的流程
2、用户层和内核层交互过程包含那两个过程?每个过程代表性的sokect接口有哪些?
3、简介信号处理的实现和其函数原型。

第五章

作业
请描述UDP客服-服务器模型实现的流程;

UDP应用程序设计中需要注意的问题是什么;

第六章

小结
过程抽象:易于维护,隐藏细节,移植
构造两个过程的例子:
connectTCP
connectUDP
给出几个客户应用的例子
DAYTIME:得到当日可读格式的时间
TIME:得到32比特整数形式的时间
ECHO: 测试网络联通性

作业
1.客户标识服务器位置的几种方式?
2.为什么TCP调用recv接收数据时要进行多次接收?
3. 理解gethostbyname、 getservbyname 和getprotobyname 的功能?
4. TCP客服服务器中客户端connect接口完成的四项任务是什么?
5.简述TCP面向连接的客户端算法和UDP无连接客户端算法

第七章

小结
服务器的简单概念:循环运行,等待请求,处理请求,发送应答
很少计算的服务,循环实现工作得好;
为了更加有效,服务器使用并发处理多个请求;为各个请求或者连接创建新线程/进程,实现并发
使用单线程可以得到表面上的并发性
客户的问题或者使用了阻塞系统调用的情况对于循环服务器以及使用单线程实现的并发服务中死锁都可能发生

作业
1、观测响应时间和请求处理时间的概念,怎样判定循环服务器是否够用?
2、服务器的四种基本类型及其特点
3、并发无连接服务器算法
4、并发面向连接的服务器算法
5、单线程实现并发、面向连接的服务器算法

第八章

小结
循环的面向连接的服务器每处理一个连接循环一次
连接达到以前在accept阻塞
建立新的连接以后创建新套接字处理
处理完毕,关闭,返回accept阻塞
DAYTIME服务
不需要客户的请求信息,检测到连接就响应
发送完响应,服务器主动关闭连接
每个连接只发送一个响应

作业
1、结合图示,描述循环面向连接服务器的进程结构
2、结合图示,描述循环无连接服务器的进程结构

第九章

小结
并发服务器通常是数据驱动的,不是下层操作系统中的时间分片机制驱动的
服务处理很少的情况下,单线程应用异步I/O管理多个连接,和多线程实现一样高效
单线程实现中,一个执行线程完成了主线程和从线程的职责
一组描述符表
使用select函数
ECHO服务器的例子

作业
1、结合图示,描述并发面向连接(单线程进程)服务器的进程结构
2、结合图示,描述单线程并发服务器的线程结构
3、int select(int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);请详细解释select函数的参数的意义,并列举该函数执行后可能出现的结果及其返回值。
4、线程与进程相比优缺点是什么?线程的同步方式有哪几种?

第十章

小结
1、多协议服务器
循环多协议服务器、
单线程并发多协议服务器
2、多服务服务器
循环无连接多服务服务器
循环有连接多服务服务器
并发面向连接多服务服务器
单线程面向连接多服务服务器
从多服务服务器调用单独的程序
3、多服务多协议设计及其案例
4、服务器静态和动态配置

作业
1、结合图示,介绍循环的、多协议服务器进程结构
2、结合图示,介绍循环有/无连接、多服务服务器进程结构
3、结合图示,介绍单线程表面并发面向连接多服务服务器进程结构
4、结合图示,介绍并发面向连接的、多服务服务器进程结构及调用单独程序的进程结构
5、描述复杂服务器的几种设计模型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值