MFC网络编程简单例程
目录
- 一、关于网络的部分概念
- 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编程的服务器端程序流程如下:
- 创建套接字(socket)
- 将套接字绑定到一个本地地址和端口上(bind)
- 将套接字设为监听模式,准备接受客户请求(listen)
- 等待客户请求到来;当请求到来时,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
- 用返回的套接字和客户端进行通信(send/recv).
- 返回,等待另一客户请求。
- 关闭套接字
基于TCP(面向连接)的socket编程的客户端程序流程如下:
- 创建套接字(socket).
- 向服务器发出连接请求(connect).
- 和服务器进行通信(send/recv).
- 关闭套接字。
服务器端的实现为
// 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编程的服务器端程序流程如下:
- 创建套接字(socket)
- 将套接字绑定到一个本地地址和端口上(bind)
- 等待接受数据(recvfrom)
- 关闭套接字
基于UDP(面向无连接)的socket编程的客户端程序流程如下:
- 创建套接字(socket).
- 向服务器发送数据(sendto).
- 关闭套接字。
注意,在基于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();
}
相关文章:

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

云原生简介 (Cloud Native)
云原生(cloud Native) 云原生的概念诞生于10年前,netflix 在 AWS 上的一次演讲中。有趣的是当初没有明确的定义,现在也没有明确的定义,对不同的人来说,有不同的概念。 概念 云原生:是在云上构…...

【SpringBoot系列】 测试框架之@SpringBootTest的使用
SpringBootTest的详细介绍 SpringBootTest 是 Spring Boot 测试框架中的注解,用于标识一个测试类,以指示该类是一个 Spring Boot 应用程序的测试类。它允许你在测试环境中加载整个 Spring Boot 应用程序上下文,测试应用程序的各种组件、服务…...

【数据结构与算法篇】手撕八大排序算法之交换排序
👻内容专栏: 《数据结构与算法篇》 🐨本文概括:常见交换排序包括冒泡排序与快速排序,本篇讲述冒泡排序与快速排序的思想及实现、复杂度分析。 🐼本文作者: 花 蝶 🐸发布时间&#…...

ArcGIS Pro实践技术应用、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合
GIS是利用电子计算机及其外部设备,采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲,它是在一定的地域内,将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来,达到对地理和属性信息的综合管理。GIS的…...

uniapp 项目实践总结(一)uniapp 框架知识总结
导语:最近开发了一个基于 uniapp 框架的项目,有一些感触和体会,所以想记录以下一些技术和经验,在这里做一个系列总结,算是对自己做一个交代吧。 目录 简介全局文件全局组件常用 API条件编译插件开发 简介 uniapp 是…...

Oracle查看与修改隐藏参数
Oracle查看与修改隐藏参数 查看隐藏参数修改隐藏参数 查看隐藏参数 查看数据库中所有的隐藏参数: SELECT a.ksppinm "Parameter", b.KSPPSTDF "Default Value",b.ksppstvl "Session Value", c.ksppstvl "Instance Value"…...

基于MQTT协议的物联网网关实现远程数据采集及监控
在数字化时代的浪潮中,工业界正面临着前所未有的变革与机遇。而在这场变革中,基于MQTT协议的物联网网关崭露头角,成为连接工业设备、实现远程数据采集与监控的利器。其中,HiWoo Box作为一款出色的工业边缘网关,引领着这…...

服务内部错误: stderr: bash: docker-compose: 未找到命令
报错描述 1Panel在应用商店安装软件失败,重建或者重启报错"服务内部错误: stderr: bash: docker-compose: 未找到命令" 执行命令"docker-compose --version"结果为"Docker Compose version v2.17.2",说明docker-compose已…...

自然语言处理(六):词的相似性和类比任务
词的相似性和类比任务 在前面的章节中,我们在一个小的数据集上训练了一个word2vec模型,并使用它为一个输入词寻找语义相似的词。实际上,在大型语料库上预先训练的词向量可以应用于下游的自然语言处理任务,为了直观地演示大型语料…...

安防监控视频平台EasyCVR视频汇聚平台定制项目增加AI智能算法详细介绍
安防视频集中存储EasyCVR视频汇聚平台,可支持海量视频的轻量化接入与汇聚管理。平台能提供视频存储磁盘阵列、视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联、H.265自动转码等功能。为了便…...

VB个人邮件处理系统设计与实现
简述 当今世界电子邮件已经是网络生活中不可或缺的,相信每个认知网络的人都会有一个或多个自己的电子邮箱,人们通过电子邮件进行通信和交流,许多商家和组织机构也用电子邮件进行各种商业活动和业务联系,毫无疑问,电子邮件已经逐渐开始取代普通的信件,成为为主流的信件交流…...

第一章辩证唯物论,考点七思维导图
逻辑框架 考点七思维导图:...

Python入门教程 - 基本函数(四)
目录 一、什么是函数 二、自定义函数并使用它 一、什么是函数 前面我们学习了像input()、print()、type()等等,他们都是函数。这些其实是由Python内部帮我们定义好的。我们直接用就可以了。 关于函数,除了用内部定义好的,我们也可以自己定…...

[PyTorch][chapter 53][Auto Encoder 实战]
前言: 结合手写数字识别的例子,实现以下AutoEncoder ae.py: 实现autoEncoder 网络 main.py: 加载手写数字数据集,以及训练,验证,测试网络。 左图:原图像 右图:重构图像 ----main----- 每轮训…...

Springboot常用方法参数注解及示例
文章目录 Springboot常用方法参数注解及示例一、RequestParam: 从URL查询参数中提取数据。二、PathVariable: 从URL路径中提取数据。三、RequestBody: 从请求体中提取数据,并映射到对象。四、RequestHeader: 从请求头中…...

基于java+springboot+vue的交流互动系统-lw
系统介绍: 随着现在网络的快速发展,网上管理系统也逐渐快速发展起来,网上管理模式很快融入到了许多企业的之中,随之就产生了“交流互动系统”,这样就让交流互动系统更加方便简单。 对于本交流互动系统的设计来说&a…...

使用candump+grep查看CAN报文
在Linux系统中观察看CAN报文,我们一般使用candump,但是有时候会发现总线上CAN报文太多,例如开启了好几个PDO,这就导致想看的报文被夹杂到报文的海洋里,然后再去找,非常麻烦。 candump也提供了只观察某个报…...

Vue中el-table表格的拖拽排序
el-table实现拖拽 element-ui 表格没有拖拽排序的功能,只能使用sortable.js插件实现拖拽排序,当然也可以应用到其他的组件里面,用法类似,这里只说表格。 实现步骤: 1、安装sortable.js npm install sortablejs --s…...

配置环境变量的作用
配置环境变量的作用 一般运行过程:寻找QQ.exe所在的目录,输入QQ.exe配置环境变量:把QQ所在的路径配给操作系统Path, 在任何路径下都能运行QQ.exe 举例: 定义变量:SCALA_HOME SCALA_HOME、JAVA_HOME 等这…...

Mysql的page,索引,Explain Type等基本常识
Mysql的基本问题 Mysql 为什么建议使用自增id? 因为id(主键)是自增的话,那么在有序的保存用户数据到页中的时候,可以天然的保存,并且是在聚集索引(id)中的叶子节点可以很好的减少插…...

【业务功能篇95】web中的重定向与转发
web接口的返回值: 转发: return “/reg” 跳转到reg的html页面 重定向 return “redirect:/login.html” 重定向重新发起请求路径是 login.html 比如我们写的接口 requestmap("/login.html")的的这个请求地址,重新请求 …...

IP对讲终端SV-6005带一路2×15W或1*30W立体声做广播使用
IP对讲终端SV-6005双按键是一款采用了ARMDSP架构,接收网络音频流,实时解码播放;配置了麦克风输入和扬声器输出,SV-6005带两路寻呼按键,可实现对讲、广播等功能,作为网络数字广播的播放终端,主要…...

ES6 新特性
🎄欢迎来到边境矢梦的csdn博文🎄 🎄本文主要梳理前端技术的JavaScript的知识点ES6 新特性文件上传下载🎄 🌈我是边境矢梦,一个正在为秋招和算法竞赛做准备的学生🌈 🎆喜欢的朋友可以…...

grafana用lark发告警python3接口
1.先在lark群聊里面创建机器人,并获取机器人链接。 2.后台运行下面python3脚本。 3.在grafana添加告警通道,设置告警。 # !/usr/bin/env python # _*_ coding: utf-8 _*_from flask import Flask, request,jsonify #import smtplib #from email.mime.te…...

Java 中数据结构HashSet的用法
Java HashSet HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。 HashSet 允许有 null 值。 HashSet 是无序的,即不会记录插入的顺序。 HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是…...

vue3下的密码输入框(antdesignvue)
参考:vue下的密码输入框 注意:这是个半成品,有些问题(input输入框加了文字间距letter-spaceing,会导致输入到第6位的时候会往后窜出来一个空白框、光标位置页会在数字前面),建议不采用下面这种方式,用另外的(画六个input框更方便) 效果预览 实现思路 制作6个小的正方…...

鸿鹄企业工程项目管理系统 Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统源代码
鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展,企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性,公司对内部工程管…...

【爬虫】5.5 Selenium 爬取Ajax网页数据
目录 AJAX 简介 任务目标 创建Ajax网站 创建服务器程序 编写爬虫程序 AJAX 简介 AJAX(Asynchronous JavaScript And XML,异步 JavaScript 及 XML) Asynchronous 一种创建交互式、快速动态网页应用的网页开发技术通过在后台与服务器进行…...

thinkphp6 入门(3)--获取GET、POST请求的参数值
一、Request对象 thinkphp提供了Request对象,其可以 支持对全局输入变量的检测、获取和安全过滤 支持获取包括$_GET、$_POST、$_REQUEST、$_SERVER、$_SESSION、$_COOKIE、$_ENV等系统变量,以及文件上传信息 具体参考:https://www.kanclou…...