【网络通信一】SOCKET套接字

[Linux-socket]将TCP客户端socket绑定到指定的interface解决方案 问题:         编写HTTP协议客户端,在指定的interface上从HTTP server上传或者下载文件。 socket代码编写过程所遇到的问题:       一开始利用socket的bind函数,将解析出来的interface的IP地址绑定到socket.        static unsigned int local_port = 1024;        阅读详情

套接字接口(socket interface)是一组函数,它们和Unix I/O函数结合起来,用以创建网络应用。

1、Socket的整体使用流程

下图表示的是用socket接口实现了典型的CS事务的具体调用流程。
在这里插入图片描述

1.1、socket基本结构体说明
  • in_port_t表示端口号数据类型
//同网络字节顺序一致,大端序(也就是一个数据的高字节放在内存地址的低地址)
typedef uint16_t in_port_t;

补充知识:目前本人亲自测验大小端的代码和结果枚举如下

#include <stdio.h>
int main(){
    union{
        int n;
        char ch;
    } data;
    
    data.n = 0x00000001;  //也可以直接写作 data.n = 1;
    if(data.ch == 1){
        printf("Little-endian\n");
    }else{
        printf("Big-endian\n");
    }
    return 0;
}
硬件操作系统大小端
浪潮盒子ARMv8 Processor rev 0 (v8l)Linux version 4.9.140-tegra小端
2080服务器Intel® Xeon® Silver 4110 CPUUbuntu 7.5.0-3ubuntu1~18.04小端
本地电脑Intel® Core™ i7-9700F CPUWindows 10小端
  • struct in_addr表示因特尔地址结构体
typedef uint32_t in_addr_t;
struct in_addr
{
    //同网络字节顺序一致,大端序(也就是一个数据的高字节放在内存地址的低地址)
    in_addr_t s_addr;
};
  • struct sockaddr_in表示套接字地址结构体
struct sockaddr_in
{
    __SOCKADDR_COMMON (sin_);//被拓展到sa_family_t sin_family;表示协议族,总是被设置为AF_INET
    in_port_t sin_port;			/* 端口号.  */
    struct in_addr sin_addr;		/* 因特尔地址  */

    /* 补齐到struct sockaddr的占位大小。以保持跟sockaddr大小一致.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
                __SOCKADDR_COMMON_SIZE -
                sizeof (in_port_t) -
                sizeof (struct in_addr)];
};
1.2、socket函数详解
  • socket函数(客户端和服务端)
/* 
若成功则返回非负的文件描述符;否则出错返回-1
此时,返回的文件描述符仅是部分打开,还不能用于读写。
需要进行后续的操作才能够进行打开套接字
*/
int socket (int __domain, int __type, int __protocol);
/*常用的传参都是如下所示的例子
AF_INET:表示我们正在使用32位IP地址
SOCK_STREAM:表示该socket套接字是连接的一个端点
*/
struct scokaddr_in sockfd = socket(AF_INET , SOCK_STREAM , 0);

  • connect函数(客户端,阻塞)

/*
在套接字__fd上与一个地址为__addr的服务器建立一个因特网连接。该函数会阻塞,一直到连接成功建立
或者是发生错误;成功后,__fd描述符就准备好可以进行读写操作了,并且得到连接的套接字对如下所示:
(客户端的IP地址:客户端的临时端口,__addr.sin_addr:__addr.sin_port)。
左边唯一确定了客户端主机上的socket连接端点
*/
//__CONST_SOCKADDR_ARG被拓展为const struct sockaddr *
int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);

  • bind函数(服务器)
/* 
在服务器进程上把__addr中的端口和地址绑定在__fd描述符上,用来和客户端建立连接。
*/
int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
  • listen函数(服务器)
/* 
socket函数创建的sockfd对应于主动套接字。
该函数将sockfd从一个主动套接字(即__fd)转化成为一个监听套接字;
返回了0表示成功,返回-1表示失败。
*/
int listen (int __fd, int __n);
  • accept函数(服务器,阻塞)
/*
 服务器等待来自客户端的连接请求到达侦听描述__fd,然后在__addr中填写客户端的套接字地址i,
 并返回一个已连接描述符,这个描述符可被用来利用Unix I/O函数与客户端通信。
 accept函数与connect函数通过三次握手信息连接成功。
*/
int accept (int __fd, __SOCKADDR_ARG __addr,
		   socklen_t *__restrict __addr_len);

注意点:区分了监听描述符和已连接描述符的作用是提供了服务器通过一个监听描述符去连接多个已连接描述符的能力,提供了并发连接的能力。

2、Socket的通信实例

2.1、服务端的通信实例
/*
 * server.c为服务器端代码
*/

#include "config.h"

int add_info(char* buf, int n){
	char* addinfo = "sb";
	if (n + 1 + strlen(addinfo) <= MAX_LINE){
		for(size_t i = 0; i < strlen(addinfo); i++){
			buf[n + i] = addinfo[i];
		}
		buf[n + strlen(addinfo)] = 0;
		return n + strlen(addinfo);
	}
	return n;
}

void printbuff(char* buf, int n){
	printf("n=%d, s=%s\n", n, buf);
	return 0;
}

int main(int argc , char **argv)
{
	/*声明服务器地址和客户链接地址*/
	struct sockaddr_in servaddr , cliaddr;

	/*声明服务器监听套接字和客户端链接套接字*/
	int listenfd , connfd;
	pid_t childpid;

	/*声明缓冲区*/
	char buf[MAX_LINE];

	socklen_t clilen;

	/*(1) 初始化监听套接字listenfd*/
	if((listenfd = socket(AF_INET , SOCK_STREAM , 0)) < 0)
	{
		perror("socket error");
		exit(1);
	}//if

	/*(2) 设置服务器sockaddr_in结构*/
	bzero(&servaddr , sizeof(servaddr));

	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //表明可接受任意IP地址
	servaddr.sin_port = htons(PORT);

	/*(3) 绑定套接字和端口*/
	if(bind(listenfd , (struct sockaddr*)&servaddr , sizeof(servaddr)) < 0)
	{
		perror("bind error");
		exit(1);
	}//if

	/*(4) 监听客户请求*/
	if(listen(listenfd , LISTENQ) < 0)
	{
		perror("listen error");
		exit(1);
	}//if

	/*(5) 接受客户请求*/
	for( ; ; )
	{
		clilen = sizeof(cliaddr);
		if((connfd = accept(listenfd , (struct sockaddr *)&cliaddr , &clilen)) < 0 )
		{
			perror("accept error");
			exit(1);
		}//if
		//打印cliaddr的信息
		printaddr(cliaddr);

		//新建子进程单独处理链接
		if((childpid = fork()) == 0) 
		{
			close(listenfd);
			//str_echo
			ssize_t n;
			char buff[MAX_LINE];
			while((n = read(connfd , buff , MAX_LINE)) > 0)
			{
				n = add_info(buff, n);
				printbuff(buff, n);
				write(connfd , buff , n);
			}
			exit(0);
		}//if
		close(connfd);
	}//for
	
	/*(6) 关闭监听套接字*/
	close(listenfd);
}

2.2、客户端的通信实例
/*
 * client.c为客户端代码
*/

#include "config.h"

/*readline函数实现*/
ssize_t readline(int fd, char *vptr, size_t maxlen)
{
	ssize_t	n, rc;
	char	c, *ptr;

	ptr = vptr;
	for (n = 1; n < maxlen; n++) {
		if ( (rc = read(fd, &c,1)) == 1) {
			*ptr++ = c;
			if (c == '\n')
				break;	/* newline is stored, like fgets() */
		} else if (rc == 0) {
			*ptr = 0;
			return(n - 1);	/* EOF, n - 1 bytes were read */
		} else
			return(-1);		/* error, errno set by read() */
	}

	*ptr = 0;	/* null terminate like fgets() */
	return(n);
}


int main(int argc , char ** argv)
{
	/*声明套接字和链接服务器地址*/
	int sockfd;
	struct sockaddr_in servaddr;

	/*判断是否为合法输入*/
	if(argc != 2)
	{
		perror("usage:tcpcli <IPaddress>");
		exit(1);
	}//if

	/*(1) 创建套接字*/
	if((sockfd = socket(AF_INET , SOCK_STREAM , 0)) == -1)
	{
		perror("socket error");
		exit(1);
	}//if

	/*(2) 设置链接服务器地址结构*/
	bzero(&servaddr , sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(PORT);
	if(inet_pton(AF_INET , argv[1] , &servaddr.sin_addr) < 0)
	{
		printf("inet_pton error for %s\n",argv[1]);
		exit(1);
	}//if

	/*(3) 发送链接服务器请求*/
	if( connect(sockfd , (struct sockaddr *)&servaddr , sizeof(servaddr)) < 0)
	{
		perror("connect error");
		exit(1);
	}//if

	/*(4) 消息处理*/
	char sendline[MAX_LINE] , recvline[MAX_LINE];
	while(fgets(sendline , MAX_LINE , stdin) != NULL)	
	{
		write(sockfd , sendline , strlen(sendline));

		if(readline(sockfd , recvline , MAX_LINE) == 0)
		{
			perror("server terminated prematurely");
			exit(1);
		}//if

		if(fputs(recvline , stdout) == EOF)
		{
			perror("fputs error");
			exit(1);
		}//if
	}//while

	/*(5) 关闭套接字*/
	close(sockfd);
}

3、编译运行方法

3.1、编译命令
#克隆项目
git clone https://github.com/pengzhikang/UnixNetLearning.git
cd tcp_socket
chmod +x run.sh
3.2、运行演示
  • 终端1输入如下命令
cd bin
./tcpser
  • 终端2输入如下命令
cd bin
./tcpcli 127.0.1.1
  • 通信测试
    在刚才的终端2中继续输入随意的一行文字
输入>123123
返回信息<sb123123
网络通信学习笔记之 ———Socket网络通信 简单介绍了基于TCP协议的Socket网络通信和基于UDP协议的Socket网路通信 阅读详情

相关推荐

【FPGA的基础快速入门23--------OV5640摄像头VGA显示】

FPGA的基础学习--------OV5640摄像头VGA显示OV5640简介二级目录三级目录 OV5640简介 OV5640同OV7725一样,都是Omni Vision(豪威科技)公司生产的CMOS图像传感器。 OV5640支持更高的分辨率(500W像素)、采集速率,具有更高的图像处理性能,主要应用在手机、数码相机、电脑多媒体等领域。 OV5640支持LED补光、MIPI(移动产业处理器接口)输出接口和DVP(数字视频并行)输出接口选择、ISP(图像信号处理)以及AFC (自动聚焦控制)等功能。 OV

暮雨中的坚果的博客 7688

socket接口详解

socket接口详解socket概述接口详解socket()   socket概述 socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层负责复杂的操作抽象为几个简单的接口供应用层调用已以实现进程在网络中的通信。 socket起源于UNIX,在Unix一切皆文件哲学的思想下,socket是一种“打开——读/写——关闭”模式的实现,服务器和客户端各自维护一个“文件”,在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通信结束时关闭文件。   接口详解 sock

L607_607的博客 9124

HDI盲埋孔设计规范:高速PCB信号完整性落地指南

盲埋孔是高密度互连(HDI)PCB实现高速信号完整性的关键技术,其本质是通过控制过孔stub长度、优化回流路径和提升布线密度,解决GHz级信号在传统通孔结构下出现的谐振、串扰与EMI超标问题。其设计核心在于叠层物理约束、电气参数建模与工艺能力协同,涉及stub长度计算、反焊盘尺寸推导、孔壁粗糙度Rz控制等关键指标。广泛应用于DDR4、PCIe Gen4、USB3.2等高速接口的PCB设计中,尤其在车载ADAS、5G基站及FPGA载板等对SI/PI要求严苛的场景中成为刚性门槛。

weixin_34416754的博客 436

Linux网络编程- sockaddr & sockaddr_in & in_addr

是用于通用的套接字地址结构体,通常在多种网络API调用中被用作参数,尤其是在套接字编程中。它是许多具体套接字地址结构体(例如用于IPv4、用于IPv6)的超类或通用类型。

青衫客36的博客 1778

Gartner《构建可扩展数据产品建设框架》心得

数据产品化:从概念到落地的实践指南 当前企业正从传统数据需求模式转向数据产品化新范式。本文系统阐述了数据产品的核心价值、定义分类和实施框架,指出成功关键是将数据包装为可复用、可扩展的产品。Gartner框架强调产品思维,提出4阶段12步实施路径,涵盖设计、工程、发布和监控全流程。文章特别提醒要避免7大常见误区,如简单重命名报表、忽视元数据治理等,建议采取MVP策略,90天内完成从价值验证到产品落地的闭环。实施中需平衡技术选型与业务需求,建立跨职能团队,并通过AARRR模型持续追踪产品价值。

2501_91410404的博客 1002

YOLOv11 网络结构详解:一文看懂 Backbone、Head、C3k2、SPPF 和 Detect 检测头

在使用 YOLOv11 进行目标检测时,我们经常会接触到或这样的模型配置文件。backbone和head分别是什么意思?ConvC3k2SPPFC2PSA这些模块分别起什么作用?P3/8、P4/16、P5/32 代表什么?为什么最后 Detect 要同时接收 3 个不同尺度的特征图?YOLOv11n、YOLOv11s、YOLOv11m、YOLOv11l、YOLOv11x 的区别在哪里?

learnerYC的博客 1809

【计算机网络】什么是socket编程?以及相关接口详解

我们使用一张图片很形象的可以看出socket所处的位置。从上图看出,Socket处于应用层与传输层的中间软件抽象层,它是一组接口。并且前面我们也学过,运输层和网络层其实属于操作系统内层面,我们只给用户提供使用的接口即可,不可能让用户能直接访问到内核部分。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。linux下一切皆文件!!!所以本质来说Socket即是一种。

luhaoran814的博客 3332

大话西游2经典单机版V8:一键架设+GM全功能+仙玉自由修改

本文详细介绍大话西游2经典单机版V8的一键架设教程和GM全功能使用指南,包括仙玉自由修改技巧。该版本无需虚拟机,解压即玩,完美还原官服经典玩法,支持离线运行,是老玩家重温经典和新玩家体验游戏的理想选择。

weixin_27303545的博客 1131

SOCKET套接字及其接口

每一个 Socket 都用一个半相关描述:{协议,本地地址,本地端口}一个完整的 Socket 则用一个相关描述{协议,本地地址,本地端口,远程地址,远程端口}每一个 Socket 有一个本地的唯一 Socket 号,由操作系统分配。

m0_58575472的博客 1542

别再死记硬背了!用TwinCAT 3手把手教你配置EtherCAT伺服驱动的PDO映射(DS402协议)

本文详细介绍了如何使用TwinCAT 3配置EtherCAT伺服驱动的PDO映射(DS402协议),涵盖环境准备、设备扫描、PDO映射实战及高级技巧。通过具体操作步骤和常见问题排查,帮助工程师快速掌握EtherCAT通信配置,提升运动控制系统的效率和稳定性。

weixin_29185493的博客 322

【图像去噪】论文复现:CLIP用于图像去噪提升泛化性!CLIPDenoising的Pytorch源码复现,跑通CLIPDenoising全流程,图文结合,网络结构梳理和拆解,对应源码注释!

论文题目:Transfer CLIP for Generalizable Image Denoising —— 用于可泛化图像去噪的转移CLIP。【图像去噪】论文精读:Transfer CLIP for Generalizable Image Denoising(CLIPDenoising)CLIPDenoising理论部分详解见上面对应的论文精读,本文以源码为主,理论部分只是粗略回顾。启发:多看其他领域的文章,分析是否能应用在去噪领域,这是产生idea的要素之一;

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 1413

Python网络通信之socket模块(一)关于套接字

关于套接字: long long ago,套接字诞生之初,它就带者伯克利分校的热血们对Unix的研究目的,将自己奉献给了计算机的本地通信,即进程间通讯(文件型通信:底层结构是文件系统来支持的,在同一台电脑上,文件系统的确可以被不同的进程访问)或者IPC,那么著名协议家族AF_UNIX(与AF_LOCAL在很多系统上二者等价,但最终没有被标准化,但python仍然使用AF_UNIX)。但自从出现

JaysenLeo 2282

彻底解决Win11锁屏界面黑屏或者图片不变化

windows锁屏后黑屏

renkai721的专栏 1万+

socket为什么翻译成“套接字”?

“套接字”这个超级别扭的术语已经存在了N长时间了。 我一直很奇怪,socket怎么就会被翻译成这样。 即便是翻译成“接口”,“插口”,“网络端口”,哪一个不比“套接字”更形象,更易于理解呢? 有没有谁知道原因? 我估计为什么大部分人愿意说socket,而不愿意说套接字,是因为和我一样,觉得这个翻译实在是太烂了!   【2008-1 bbs】...

无名刀客 569

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

java socket编程_Java TCP/IP Socket编程

Hello,朋友们,你们的小果又来啦!本文主要介绍下支持TCP/IP协议的Socket编程。Socket(套接字)是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。套接字通常和同一个域中的套接字交换数据(数据交换...

weixin_39580042的博客 448

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

套接字

网络上的两个程序通过一个双向的通信连接实现数据的交换,建立网络通信连接至少要一对端口号(socket)。Socket的英文原义是“孔”或“插座”,通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。 套接管:两个管子的接口处用以将两个管口连接在一起的套筒。 socket 承物的凹处;承口;插座;窝,孔。 套接:适配、连接; 字:语柄。 套接管、...

diaoju3333的博客 105

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

套接字通信

套接字(socket)为通信的端点,每个套接字由一个 IP 地址和一个端口号组成。通过网络通信的每对进程需要使用一对套接字,即每个进程各有一个。 通常,套接字采用客户机-服务器架构。服务器通过监听指定端口,来等待客户请求。服务器在收到请求后,接受来自客户套接字的连接,从而完成连接。 流程 服务器先用 socket 函数来建立一个套接字,用这个套接字完成通信的监听。 用 bind 函数来绑定一个端口号和 IP 地址。因为本地计算机可能有多个网址和 IP,每一个 IP 和端口有多个端口。需要指定一个 I

weixin_38051797的博客 738

网络通信 --- Socket套接字

🥦一、socket套接字 🍌1.什么是socket 🍋2.socket的原理 🌲二、UDP数据报套接字编程 🍁1.DatagramSocket 🍂2.DatagramPacket 🍀3.InetSocketAddress 🍃4.基于 UDP socket 的回显服务器 🌳三、TCP数据报套接字编程 🍎1.ServerSocket 🍅2.Socket 🍓3.基于 TCP socket 的回显服务器

m0_64247824的博客 3502

socket库:Python网络通信套接字

目录前言什么是套接字?地址簇套接字类型套接字的简单应用gethostbyname_ex()与gethostbyname()getservbyname()与getservbyport() 前言 socket库提供了一个底层C API,可以使用BSD套接字接口实现网络通信。它包括socket类,用于处理具体的数据通道,还包括用来完成网络相关任务的函数,如将一个服务器名转换为一个地址以及格式化数据以便在网络上发送。 什么是套接字? 套接字是程序在本地或者通过互联网来回传递数据时所用通信通道的一个端点。 套接字有2

李元静 2815

【网络】socket——预备知识 | 套接字 | UDP网络通信

介绍了socket编程的一些预备知识,还有套接字用到的系统调用和注意事项,以及UDP网络通信的原理和实现,还有用户层和网络之间的解耦。

weixin_63726869的博客 5091

网络通信与Socket套接字详解

本文系统介绍了网络通信的基本原理与Socket套接字技术。主要内容包括:1)网络通信五层模型(物理层、数据链路层、网络层、传输层和应用层)及数据封装/分用流程;2)IP地址、端口号、网络协议等核心概念;3)TCP/UDP协议的特性对比(有/无连接、可靠/不可靠传输等);4)Socket套接字分类(原始套接字、流套接字和数据报套接字)及其在TCP/IP协议栈中的位置。文章通过日常生活中的快递类比,生动解释了网络通信的抽象概念,为后续网络编程实践奠定了理论基础。

2303_80388948的博客 1631

Linux下套接字详解(二)----套接字Socket

在前面我们讲了TCP/IP、TCP和UDP的一些基本知识,但是协议只有一套,而我们系统多个TCP连接或多个应用程序进程必须通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口。套接口可以说是网络编程中一个非常重要的概念,linux以文件的形式实现套接口,与套接口相应的文件属于sockfs特殊文件

OSKernelLAB(gatieme) 2万+

【C++】网络通信-Socket

C++网络通信Socket套接字

IdealSanX的博客 3379

什么是套接字(Socket)

应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要 通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字 (Socket)的接口,区分不同应用程序进程间的网络通信和连接。 生成套接字,主要有3个参数:通信的目的IP地址、使用的传输 ...

luzhensmart的专栏 9万+

【网络通信】socket编程——TCP套接字

TCP依旧使用代码来熟悉对应的套接字,很多接口都是在udp中使用过的所以就不会单独把他们拿出来作为标题了,只会把第一次出现的接口作为标题。

qq_62939852的博客 2429

Socket套接字学习(一)

<br />1.套接字(socket)<br />       一个完整的网络应用程序包括客户端和服务器两个部分。网间通信进程需要由两个进程组成,并且只能用同一种协议。也就是说,不能在通信的一端使用TCP协议,而另一端则用UDP协议。一个完整的网络通信需要一个五元组来标识:协议、本地地址、本地端口号、远端地址、远端端口号。<br />       应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输

cxh342968816的专栏 1万+
上一篇: 你或许也想拥有专属于自己的AI模型文件格式(推理部署篇)-(9)
下一篇: 为Halide安装opencl支持
慷仔
博客等级 码龄9年 88粉丝 46原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值