MFC网络编程简单例程

news2024/12/25 12:24:22

目录

  • 一、关于网络的部分概念
    • 1 URL(网址)及URL的解析
    • 2 URL的解析
    • 3 域名及域名解析
    • 3 IP及子网掩码
    • 4 什么是Web服务器
    • 5 HTTP的基本概念
    • 6 Socket库概念
    • 7 协议栈
    • 8 Socket库收发数据基本步骤
  • 二、基于TCP的网络应用程序
  • 三、基于UDP的网络应用程序

一、关于网络的部分概念

1 URL(网址)及URL的解析

 网址:学名叫URL(Uniform Resource Locator),统一资源定位符。URL的各种形式如下图所示。
在这里插入图片描述
 尽管URL有各种不同的写法,但他们有一个共同点,就是URL开头的文字,即“http:”“ftp:”“file:”"mailto:"这部分文字标识浏览器应当使用的访问方法。比如当访问Web服务器时应当使用HTTP协议,而访问FTP服务器时应当使用FTP协议。因此,我们可以把这部分理解为访问时使用的协议类型。

2 URL的解析

 浏览器先要解析URL,从而生成发送给Web服务器的请求消息。以下我们以访问Web服务器为例进行讲解,假定URL为http://www.lab.glasscom.com/dir1/file1.html ,经过浏览器解析之后,可以看到拆分结果为:Web服务器名称www.lab.glasscom.com,以及文件的路径名/dir1/file1.html
在这里插入图片描述
在这里插入图片描述

3 域名及域名解析

 一般来说,域名包括顶级域名、一级域名、子域名组成,其格式为www.A.B.C.com,句点划分了域名的层次结构,越靠右的域(如com)的层次越高。假设DNS服务器和域一一对应(实际上比较复杂),则上层域的DNS服务器保存着下级服务器的信息,因此可以一层一层顺藤摸瓜地查找下去。
在这里插入图片描述
 对地址为 http://www.lab.glasscom.com/dir1/file1.html 的URL来说,其中的www.lab.glasscom.com就是域名。
 当我们在浏览器输入一个域名后,需要进行域名解析,也就是通过操作系统Socket库中的解析器向最近的DNS服务器查询域名对应的IP地址,获得此地址后,我们才能同该服务器进行通信。

3 IP及子网掩码

 互联网和公司内部的局域网都是基于TCP/IP的思路来设计的,也就是由一些小的子网,通过路由器连接起来组成一个大的网络。这里的子网可以理解为用集线器连接起来的几台计算机,我们将它看作一个单位,成为子网。将子网通过路由器连接起来,就形成了一个网络。在网络中,所有的设备都会被分配一个地址。这个地址就相当于现实中某条路上的“XX号XX室”。其中“号”对应的号码是分配给整个子网的,而“室”对应的号码室分配给子网中的计算机的,这就是网络中的地址。“号”对应的号码称为网络号,“室”对应的号码称为主机号,这个地址的整体称为IP地址。
 准确的说,IP地址是连接在Internet中的每一台主机(或 路由器)的全球唯一的标识符。实际的IP地址是一串32比特的数字,按照8比特为一组分成4组,分别用十进制标识然后再用原点隔开。但是这样我们就无法区分哪些是网络号,哪些是主机号。为此,我们附加了子网掩码。
在这里插入图片描述
 子网掩码为1的部分表示网络号,子网掩码为0的部分表示主机号,如下图所示。
在这里插入图片描述

4 什么是Web服务器

  Web服务器一般指的是“网站服务器”,也称为WWW(Word Wide Web)服务器,是某种驻留在因特网上的计算机程序,可以向请求终端提供服务,主要功能时存储、处理和传递网页给“客户”,传递内容一般是HTML文档、图像、样式表或脚本等,也可以放置网站文件以供浏览或下载。严格来说Web服务器只负责处理Http协议请求,发送静态页面的内容。

5 HTTP的基本概念

 在浏览器解析完URL之后,就会使用HTTP协议访问Web服务器。那么HTTP协议到底是什么?
在这里插入图片描述
 HTTP 协议定义了客户端和服务器之间交互的消息内容和步骤,其基本思路非常简单。首先,客户端会向服务器发送请求消息。请求消息中包含的内容是“对什么”和“进行怎样的操作”两个部分。其中相当于“对什么”的部分称为 URI。一般来说,URI 的内容是一个存放网页数据的文件名或者是一个 CGI 程序的文件名,例如“/dir1/file1.html” “/dir1/program1.cgi”等。不过,URI 不仅限于此,也可以直接使用“http:”开头的 URL 来作为 URI。换句话说就是,这里可以写各种访问目标,而这些访问目标统称为 URI。
 相当于接下来“进行怎样的操作”的部分称为方法。方法表示需要让Web 服务器完成怎样的工作,其中典型的例子包括读取 URI 表示的数据、将客户端输入的数据发送给 URI 表示的程序等。下表列举了主要的方法,通过这张表大家应该能够理解通过方法可以执行怎样的操作。
在这里插入图片描述
 HTTP 消息中还有一些用来表示附加信息的头字段。客户端向 Web 服务器发送数据时,会先发送头字段,然后再发送数据。收到请求消息之后,Web 服务器会对其中的内容进行解析,通过 URI和方法来判断“对什么”“进行怎样的操作”,并根据这些要求来完成自己的工作,然后将结果存放在响应消息中。在响应消息的开头有一个状态码,它用来表示操作的执行结果是成功还是发生了错误。当我们访问 Web 服务器时,遇到找不到的文件就会显示出 404 Not Found 的错误信息,其实这就是状态码。状态码后面就是头字段和网页数据。响应消息会被发送回客户端,客户端收到之后,浏览器会从消息中读出所需的数据并显示在屏幕上。到这里,HTTP 的整个工作就完成了。

6 Socket库概念

 Socket库是操作系统提供的一个库,包含的程序组件可以让其他的程序调用操作系统的网络功能。如域名解析器就是库中的一个组件。
 当浏览器和 Web 服务器通信时、通过 DNS 服务器查询 IP 地址时,都需要使用 Socket 库中的程序组件。
 使用 Socket 库来收发数据的操作过程如下图所示 。简单来说,收发数据的两台计算机之间连接了一条数据通道,数据沿着这条通道流动,最终到达目的地。我们可以把数据通道想象成一条管道,将数据从一端送入管道,数据就会到达管道的另一端然后被取出。数据可以从任何一端被送入管道,数据的流动是双向的。不过,这并不是说现实中真的有这么一条管道,只是为了帮助大家理解数据收发操作的全貌。
在这里插入图片描述

7 协议栈

 协议栈是指操作系统中的网络控制软件,协议栈的内部结构为:
在这里插入图片描述
 图中最上面的部分是网络应用程序,也就是浏览器、电子邮件客户端、Web 服务器、电子邮件服务器等程序,它们会将收发数据等工作委派给下层的部分来完成。当然,除了浏览器之外,其他应用程序在网络上收发数据的操作也都是类似上面这样的,也就是说,尽管不同的应用程序收发的数据内容不同,但收发数据的操作是共通的。
 应用程序的下面是 Socket 库,其中包括解析器,解析器用来向 DNS服务器发出查询。再下面就是操作系统内部了,其中包括协议栈。协议栈的上半部分有两块,分别是负责用 TCP 协议收发数据的部分和负责用 UDP 协议收发数据的部分,它们会接受应用程序的委托执行收发数据的操作。
 TCP 和UDP是面向传输层的两种协议;像浏览器、邮件等一般的应用程序都是使用 TCP 收发数据的,而像 DNS 查询等收发较短的控制数据的时候则使用 UDP。
 总的来说,上层向下层发出指令,下层执行上层指令;应用程序调用Socket库,Socket库调用了协议栈,协议栈又调用了网卡驱动程序,最终将消息发送出去。

8 Socket库收发数据基本步骤

 利用socket收发数据的操作分为若干个阶段,可以大致总结为以下 4 个。
  1.创建套接字(创建套接字阶段)
  2.将管道连接到服务器端的套接字上(连接阶段)
  3.收发数据(通信阶段)
  4.断开管道并删除套接字(断开阶段)

客户端和服务器之间收发数据操作的情形
在这里插入图片描述

二、基于TCP的网络应用程序

 基于TCP(面向连接)的socket编程的服务器端程序流程如下:

  1. 创建套接字(socket)
  2. 将套接字绑定到一个本地地址和端口上(bind)
  3. 将套接字设为监听模式,准备接受客户请求(listen)
  4. 等待客户请求到来;当请求到来时,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
  5. 用返回的套接字和客户端进行通信(send/recv).
  6. 返回,等待另一客户请求。
  7. 关闭套接字

 基于TCP(面向连接)的socket编程的客户端程序流程如下:

  1. 创建套接字(socket).
  2. 向服务器发出连接请求(connect).
  3. 和服务器进行通信(send/recv).
  4. 关闭套接字。

 服务器端的实现为

// TCPSrv.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <Winsock2.h>
#include <iostream>
#include <ws2tcpip.h>

//#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib, "Ws2_32.lib")

int main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD(2, 2);

	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		return EXIT_SUCCESS;
	}

	/* Confirm that the WinSock DLL supports 2.2.*/
	/* Note that if the DLL supports versions greater    */
	/* than 2.2 in addition to 2.2, it will still return */
	/* 2.2 in wVersion since that is the version we      */
	/* requested.                                        */

	if (LOBYTE(wsaData.wVersion) != 2 ||
		HIBYTE(wsaData.wVersion) != 2) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup();
		return EXIT_SUCCESS;
	}


	//第一步:创建套接字
	SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);

	//第二步:将套接字绑定到本地地址和端口上
	SOCKADDR_IN addSrv;
	//使用网络字节序,可以将IP地址指定为INADDR_ANY,允许套接字向任何分配给
	//本地机器的IP地址发送或接受数据。
	//如果我们想让套接字使用多个IP中的一个地址,就必须指定实际地址,这需要用到
	//inet_addr函数来实现
	addSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addSrv.sin_family = AF_INET;
	addSrv.sin_port = htons(6000);	
	bind(sockSrv, (SOCKADDR*)&addSrv, sizeof(SOCKADDR));//绑定套接字

	//第三步:将套接字设为监听模式,准备接受客户请求,
	//第二个参数是指等待连接队列的最大长度,比如说此时等待连接队列是5,那么下一个连接请求会被拒绝
	listen(sockSrv, 5);

	SOCKADDR_IN addrClient;
	int len = sizeof(SOCKADDR);
	while (true)
	{
		//第四步:等待客户连接到来
		//accept 函数提取套接字 s 上挂起连接队列上的第一个连接。然后,它会创建一个新的套接字,并将其句柄并将其返回。
		//新创建的套接字是将处理实际连接的套接字;它具有与套接字相同的属性,包括使用 WSAAsyncSelect 或 WSAEventSelect 函数注册的异步事件。
		SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
		char sendBuf[100];
		sprintf_s(sendBuf, "Welcome %s to http://www.sunxin.org", inet_ntoa(addrClient.sin_addr));

		//第五步:用返回的套接字和客户端通信
		//发送数据,为了让接收端在接受数据以后,可以在该数据字符串之后增加一个“\0”结尾标志
		send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
		char recvBuf[100];
		//接收数据
		recv(sockConn, recvBuf, 100, 0);

		//打印接受到的数据
		printf("%s\n", recvBuf);
		//第六步:关闭套接字,此时程序进入到下一循环
		closesocket(sockConn);
	}
}

 客户端的实现如下

// TCPClient.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <Winsock2.h>
#include <iostream>
#include <ws2tcpip.h>

#pragma comment(lib, "Ws2_32.lib")

int main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD(2, 2);

	//加载套接字库
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		return EXIT_SUCCESS;
	}

	if (LOBYTE(wsaData.wVersion) != 2 ||
		HIBYTE(wsaData.wVersion) != 2) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup();
		return EXIT_SUCCESS;
	}

	//第一步:创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

	//第二部:向服务器发送连接请求
	SOCKADDR_IN addrSrv;
	//地址127.0.0.1 是本地回路地址。主机环回是指地址为 127.0.0.1 的任何数据包
	//都不应该离开计算机(主机),发送它——而不是被发送到本地网络或互联网,它只是被自己“环回”,
	//并且发送数据包的计算机成为接收者。
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(6000);
	connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

	//第三步:和服务器进行通信
	//接受数据
	char recvBuf[100];
	recv(sockClient, recvBuf, 100, 0);
	printf("%s\n", recvBuf);
	//发送数据
	send(sockClient, "This is lisi", strlen("This is lisi") + 1, 0);

	//第四步:关闭套接字
	closesocket(sockClient);

	//释放资源
	WSACleanup();
	getchar();
}

三、基于UDP的网络应用程序

 基于UDP(面向无连接)的socket编程的服务器端程序流程如下:

  1. 创建套接字(socket)
  2. 将套接字绑定到一个本地地址和端口上(bind)
  3. 等待接受数据(recvfrom)
  4. 关闭套接字

基于UDP(面向无连接)的socket编程的客户端程序流程如下:

  1. 创建套接字(socket).
  2. 向服务器发送数据(sendto).
  3. 关闭套接字。

  注意,在基于UDP的套接字编程时,利用的是sendto和recvfrom两个函数;而基于TCP的套接字编程时,发送和接受分别使用send和recv函数。
  服务器端的程序实现如下:

// UDPSrv.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <Winsock2.h>
#include <iostream>
#include <ws2tcpip.h>

#pragma comment(lib, "Ws2_32.lib")

int main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD(2, 2);

	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		return EXIT_SUCCESS;
	}

	if (LOBYTE(wsaData.wVersion) != 2 ||
		HIBYTE(wsaData.wVersion) != 2) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup();
		return EXIT_SUCCESS;
	}

	//第一步:创建套接字
	SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);

	//第二步:将套接字绑定到一个本地地址和端口上
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(6000);
	bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

	//第三步:等待接收数据
	SOCKADDR_IN addrClient;
	int len = sizeof(SOCKADDR);
	char recvBuf[100];
	recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrClient, &len);
	printf("%s\n", recvBuf);

	//第四步:关闭套接字
	closesocket(sockSrv);

	WSACleanup();
	getchar();
}

 客户端的程序实现如下:

// UDPClient.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <Winsock2.h>
#include <iostream>
#include <ws2tcpip.h>

#pragma comment(lib, "Ws2_32.lib")

int main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD(2, 2);

	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		return EXIT_SUCCESS;
	}

	if (LOBYTE(wsaData.wVersion) != 2 ||
		HIBYTE(wsaData.wVersion) != 2) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup();
		return EXIT_SUCCESS;
	}

	//第一步:创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(6000);

	//第二步:向服务器发送数据(sendto)
	sendto(sockClient, "Hell0", strlen("Hello") + 1, 0, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

	//第三步:关闭套接字
	closesocket(sockClient);

	WSACleanup();
	getchar();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/946604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低代码的探索之路

Gartner发布报告指出&#xff0c;2023年全球低代码开发平台市场规模将达到345亿美元&#xff0c;比2022年增长20%。 目前&#xff0c;国内外已经有许多低代码平台&#xff0c;包括OutSystems、Mendix、Appian、Microsoft Power App等。这些平台提供了丰富的功能和工具&#xff…

故障演练实战

做了两年多的故障演练&#xff0c; 一直想聊聊自己对故障演练的理解&#xff0c;但是每次提起笔都不知道写一些什么。 什么是故障演练 为什么要做故障演练 在没做故障演练之前&#xff0c;我想很多人可能和我有一样的想法&#xff0c;我的系统跑了好多年&#xff0c;也没出什么…

Docker容器数据持久化

Docker容器数据持久化 Docker容器数据卷&#xff1a;volumes 1、什么是数据卷&#xff1f; 数据卷是经过特殊设计的目录&#xff0c;可以绕过联合文件系统&#xff0c;为一个或者多个容器提供访问&#xff0c;数据卷设计的目的&#xff0c;在于数据的永久存储&#xff0c;它完…

Java-day11(集合)

集合 1.集合框架 用于存储数量不等的多个对象&#xff0c;还可用于保存具有映射关系的关联数组 Java集合可分为Collection和Map两种体系 Collection接口 Set:元素无序&#xff0c;不可重复的集合----&#xff08;类似数学中的集合&#xff09; List:元素有序&#xff0c;可重…

linux内网yum源服务器搭建

1.nginx: location / {root /usr/local/Kylin-Server-V10-SP3-General-Release-2303-X86_64;autoindex on;autoindex_localtime on;autoindex_exact_size off; } 注:指定到镜像的包名 2.修改yum源地址 cd /etc/yum.repos.d/vim kylin_x86_64.repo 注: --enabled设置为1 3.重…

Android Studio 的github 工程克隆

上文介绍了Android Studio 里的"Git 建立和简单操作。本文介绍从github 上的工程fork 和clone到本地&#xff0c;然后学习和改进。 本文参考 https://learntodroid.com/how-to-use-git-and-github-in-android-studio/ 克隆clone Github 仓库&#xff1a; 先 Fork 你选择…

仓储23代拣货标签操作指导

服务器使用 V1.4基站已经内置服务程序&#xff0c;无需搭建服务&#xff1b;可跳至第1.4部分 服务器搭建 安装mysql5.7, 创建db_wms数据库并导入原始数据库文件 安装jdk1.8, 配置java环境变量 下载tomca8.0, 部署wms.war到tomcat, 并启动tomcat 下载资源 Windows 64bit: …

知乎如何精准引流?

知乎&#xff0c;用过的人都知道&#xff0c;它是一个相当重要的引流平台。因为它用户规模大、粘性高、活跃性强、百度权重高&#xff0c;流量也相对精准&#xff0c;这也意味者变现能力强。 做引流的朋友都知道&#xff0c;想要把用户从别的平台引流到自己微信上&#xff0c;就…

Gradle项目如何开启debug?

一、打开Idea的终端&#xff0c;输入命令gradle build --debug 开启构建DeBug模式 二、点击编辑配置&#xff0c;并填写自己debug的名称 三、编辑好debug配置后&#xff0c;点击以下debug按钮&#xff0c;就可以开始调试代码了。

vue3下的密码输入框(antdesignvue)

参考:vue下的密码输入框 注意:这是个半成品,有些问题(输入到第6位的时候会往后窜出来一个空白框、光标位置会在数字前面),建议不采用下面这种方式,用另外的(画六个input框更方便) 效果预览 实现思路 制作6个小的正方形div 用一个input覆盖在6个div上 给input设置透明(…

LabVIEW开发油气井管道内无线通信微波系统

LabVIEW开发油气井管道内无线通信微波系统 由于石油和天然气行业的重要性&#xff0c;许多公司和研究人员正在研究和开发新的通信和传感器技术。需要解决的问题与管道状况、地震活动、腐蚀水平、可能的气体泄漏检测和其他性能问题的实时和连续监测有关。处理这些问题的最广泛使…

forlium 笔记 Map

用于创建交互式地图 1 主要参数 1.1. location 地图位置 地图的经纬度 import foliumm folium.Map(location[31.186358, 121.510256],zoom_start15)m 1.2 tiles 内置样式 默认是OpenStreetMap 1.2.1 Stamen Terrain 它强调了地形特征&#xff0c;如山脉、河流和道路 m …

9、Spring_事务管理

六、Spring 事务管理 1.Spring 事务简介 事务概述&#xff1a;保证数据库操作同时成功或者同时失败 Spring 事务的概述&#xff1a;在数据层保证数据库操作同时成功或者同时失败 2.转账案例分析 转账肯定有一个业务方法&#xff1a;给转出用户减钱&#xff0c;给转入用户加…

Java+Github+Jenkins部署

Java项目—Jenkins部署笔记 一&#xff0c;准备 一台服务器操作系统&#xff0c;示例为ubuntu 22.0.4 可运行lsb_release -a查看 二&#xff0c;安装 docker 更新软件包列表&#xff1a; sudo apt update安装必要的软件包&#xff0c;以便使用HTTPS通过APT下载软件包&#x…

财务大模型,产业路向何方?

无论过去还是将来&#xff0c;财务的角色和意义都不会被颠覆&#xff0c;只会被清晰化&#xff0c;只会回归到本源。 作者|思杭 编辑|皮爷 出品|产业家 “今年&#xff0c;我们被市场倒逼着做数字化转型。一切都被打乱了&#xff0c;像这样的转变是前所未有的。到了8月&…

泰迪大数据实训平台产品介绍

大数据产品包括&#xff1a;大数据实训管理平台、大数据开发实训平台、大数据编程实训平台等 大数据实训管理平台 泰迪大数据实训平台从课程管理、资源管理、实训管理等方面出发&#xff0c;主要解决现有实验室无法满足教学需求、传统教学流程和工具低效耗时和内部教学…

hadoop 学习:mapreduce 入门案例三:顾客信息与订单信息相关联(联表)

这里的知识点在于如何合并两张表&#xff0c;事实上这种业务场景我们很熟悉了&#xff0c;这就是我们在学习 MySQL 的时候接触到的内连接&#xff0c;左连接&#xff0c;而现在我们要学习 mapreduce 中的做法 这里我们可以选择在 map 阶段和reduce阶段去做 数据&#xff1a; …

聚合支付-第3章-支付宝支付接入指南

惠民支付 第3章讲义-支付宝接入指南 支付宝接入步骤: 1、进入网址https://open.alipay.com/develop/manage 2、扫码登录支付宝账号&#xff0c;控制台&#xff0c;最下边有一个沙箱环境 3、在“支付宝开放平台开发助手”软件中生成密钥&#xff0c;点击生成密钥&#xff0c;保…

Axure RP 8.1.0.3400(原型设计工具)

Axure RP 8是一款原型设计工具&#xff0c;它提供了丰富的功能和工具&#xff0c;帮助用户创建高质量的网页、移动应用和桌面软件原型。以下是Axure RP 8的一些特色介绍&#xff1a; 强大的交互设计&#xff1a;Axure RP 8支持创建复杂的动画和过渡效果&#xff0c;让你的原型更…

一文彻底扒光 Handler

作者&#xff1a;HenAndroid 典型的生产者-消费者模式。 Android跨进程要掌握的是Binder, 而同一进程中最重要的应该就是Handler 消息通信机制了。我这么说&#xff0c;大家不知道是否认同&#xff0c;如果认同&#xff0c;还希望能给一个关注哈。 Handler 是什么&#xff1f;…