TCP / UDP 概念 + 实验(计网自顶向下)

Github源码

moranzcw/Computer-Networking-A-Top-Down-Approach-NOTES: 《计算机网络-自顶向下方法(原书第6版)》编程作业,Wireshark实验文档的翻译和解答。 (github.com)

暂定打算分2步走,前置是中科大对应计网黑书的视频

第1步完成14个WireShark实验,5个课后实验(共19个计网实验)

第2步,还有时间的话,cs144的实验跟一遍,没时间就直接开始tinyWebserver

目录

🌹关于 Socket

💧预习 TCP

🌼概念

🌼原理

🌼结构体

🌼部分代码

(1)服务器的Socket编程  -- sockaddr_in

(2)客户端的Sockets编程 -- hostent

💧预习 UDP

(1)客户端 UDP Socket

(2)服务器 UDP Socket

🔥TCP套接字(实验1)

(1)过程

(2)代码

(3)详细解释

🎂服务器

🎂客户端

🔥UDP套接字(实验2)


🌹关于 Socket

Socket,即“套接字”,是计网中通信的一种机制。

它提供的接口,使得app不用关心底层协议的细节。

(1)功能上

实现进程间数据传输,不同计算机的交互。

可用于实现 C / S 模型(client / server)(客户端 / 服务器)

实现对等通信模型(P2P)

(2)网络层次上

位于应用层和传输层之间。

它通过封装传输层的协议(TCP / UDP),为应用层提供统一的接口。

将应用层数据包装成传输层数据报文,发送到网络,

同时也接受传输层的数据报文,解析后交给应用层处理。

(3)协议栈上

Socket是基于网络协议栈的接口,位于app与OS内核之间。

app通过Socket API调用函数,向OS内核发送请求,

内核根据Socket API指定的网络协议(TCP / UDP),使用对应协议栈完成传输和接受。

💧预习 TCP

🌼概念

socket 原意是插口,每个插口对应一个编号

插口就是 socket 服务(插孔对应的编号就是端口号,插头也是一个 socket 服务)

Socket(套接字)到底是什么呢?👇

(1)所以,socket 即两个应用程序通过一个双向的通信连接实现数据交换,连接的这一段就是 socket(又称 套接字

(2)套接字:网络中不同主机上的应用进程之间进行双向通信的端点的抽象,一个 套接字,就是网络上进程通信的一端(上联应用进程,下联网络协议栈)

(3)进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点

(4)由 IP地址 和 端口 结合,提供向应用层进程传送数据包的机制

实现一个 socket 连接通信至少需要 2 个套接字,一个运行在服务端(插孔),一个运行在客户端(插头)

Socket 是应用层 与 传输层(TCP/IP协议簇)的抽象中间层 

不同于OSI模型的七个分层,TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中。

  • 应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等
  • 传输层:TCP,UDP
  • 网络层:IP,ICMP,OSPF,EIGRP,IGMP
  • 数据链路层:SLIP,CSLIP,PPP,MTU

Socket是什么 - 简书 (jianshu.com)

【网络编程知识】什么是Socket?概念及原理分析-云社区-华为云 (huaweicloud.com)

🌼原理

场景

打电话给女朋友要先拨号,女朋友听到响铃会拿起电话,此时按时你就和女朋友建立了连接,就可以通话了。

交流完后,挂断电话结束本次交流。

原理

漏了个,客户端 close()后,服务端还有个 read(),然后服务端最后 close()

“3次握手,4次挥手”及相关细节补充👇

TCP和UDP的传输过程以及二者之间的区别_数据通信分tcp和udp,属于什么过程-CSDN博客

TCP和UDP的区别 - notes (gitbook.io)

🌼结构体

数据结构1

数据结构2

🌼部分代码

(以下是GPT给的代码,Windows下,codeblocks里无法运行 --

-- 需要到Linux下运行。此处只是对原理进行代码解释)

(1)服务器的Socket编程  -- sockaddr_in

struct sockaddr_in {short sin_family;  // 地址族,一般为AF_INET(IPv4)unsigned short sin_port;  // 端口号struct in_addr sin_addr;  // IPv4地址char sin_zero[8];  // 填充字段,通常不需要使用
};
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {// 创建socketint serverSocket = socket(AF_INET, SOCK_STREAM, 0);// 设置服务器地址和端口sockaddr_in serverAddress{};serverAddress.sin_family = AF_INET;  // 地址族为IPv4serverAddress.sin_addr.s_addr = INADDR_ANY;  // 使用本地任意可用IP地址serverAddress.sin_port = htons(8080);  // 监听8080端口// 绑定socket到服务器地址和端口bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));// 监听连接请求listen(serverSocket, 5);std::cout << "Server started. Waiting for connections..." << std::endl;while (true) {// 接受客户端连接sockaddr_in clientAddress{};socklen_t addrSize = sizeof(clientAddress);int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &addrSize);std::cout << "New connection accepted" << std::endl;// 读取客户端发来的数据char buffer[1024];ssize_t bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);std::cout << "Received message: " << buffer << std::endl;// 向客户端发送响应数据const char* response = "Hello from server!";send(clientSocket, response, strlen(response), 0);// 关闭客户端连接close(clientSocket);}// 关闭服务器socketclose(serverSocket);return 0;
}

(2)客户端的Sockets编程 -- hostent

struct hostent {char* h_name;           // 官方名称char** h_aliases;       // 别名列表int h_addrtype;         // 地址类型(一般为AF_INET)int h_length;           // 地址长度(一般为4字节)char** h_addr_list;     // IP地址列表
};
#include <iostream>
#include <netdb.h>
#include <arpa/inet.h>int main() {const char* hostname = "www.example.com";// 通过主机名获取hostent结构体struct hostent* host = gethostbyname(hostname);if (host == nullptr) {std::cerr << "Failed to get host information" << std::endl;return 1;}// 输出主机名和别名std::cout << "Hostname: " << host->h_name << std::endl;for (char** alias = host->h_aliases; *alias != nullptr; ++alias) {std::cout << "Alias: " << *alias << std::endl;}// 输出IP地址for (char** address = host->h_addr_list; *address != nullptr; ++address) {sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(*address);std::cout << "IP Address: " << inet_ntoa(addr->sin_addr) << std::endl;}return 0;
}

💧预习 UDP

UDP是面向无连接的协议,不需要像TCP一样建立连接和关闭连接。因此,UDP服务器和客户端都只需分别创建一个socket,并通过sendto()recvfrom()发送和接收数据,不需要调用accept()bind()函数

代码源于GPT,需要在Linux下运行 (此处只供学习,不一定能跑通)

结构体👇

struct sockaddr_in {short sin_family;  // 地址族,一般为AF_INET(IPv4)unsigned short sin_port;  // 端口号struct in_addr sin_addr;  // IPv4地址char sin_zero[8];  // 填充字段,通常不需要使用
};

(1)客户端 UDP Socket

#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {// 创建socketint clientSocket = socket(AF_INET, SOCK_DGRAM, 0);// 设置服务器地址和端口sockaddr_in serverAddress{};serverAddress.sin_family = AF_INET;  // 地址族为IPv4serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");  // 服务器IP地址serverAddress.sin_port = htons(8080);  // 服务器端口号// 发送消息到服务器const char* message = "Hello from client!";sendto(clientSocket, message, strlen(message), 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress));// 接收服务器响应char buffer[1024];ssize_t bytesRead = recvfrom(clientSocket, buffer, sizeof(buffer), 0, nullptr, nullptr);std::cout << "Received response: " << buffer << std::endl;// 关闭客户端socketclose(clientSocket);return 0;
}

(2)服务器 UDP Socket

#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {// 创建socketint serverSocket = socket(AF_INET, SOCK_DGRAM, 0);// 设置服务器地址和端口sockaddr_in serverAddress{};serverAddress.sin_family = AF_INET;  // 地址族为IPv4serverAddress.sin_addr.s_addr = INADDR_ANY;  // 使用本地任意可用IP地址serverAddress.sin_port = htons(8080);  // 监听8080端口// 绑定socket到服务器地址和端口bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));std::cout << "Server started. Waiting for messages..." << std::endl;while (true) {// 接收客户端消息char buffer[1024];sockaddr_in clientAddress{};socklen_t addrSize = sizeof(clientAddress);ssize_t bytesRead = recvfrom(serverSocket, buffer, sizeof(buffer), 0, (struct sockaddr*)&clientAddress, &addrSize);std::cout << "Received message from " << inet_ntoa(clientAddress.sin_addr) << ":" << ntohs(clientAddress.sin_port) << std::endl;std::cout << "Message: " << buffer << std::endl;// 向客户端发送响应数据const char* response = "Hello from server!";sendto(serverSocket, response, strlen(response), 0, (struct sockaddr*)&clientAddress, addrSize);}// 关闭服务器socketclose(serverSocket);return 0;
}

🔥TCP套接字(实验1)

(1)过程

1,vscode先配置py环境

2,搞乱了需要彻底重装:如何完全重置或卸载vscode_哔哩哔哩_bilibili

3,Github源码git clone到本地,解压缩,并导入vscode👇

4,打开cmd,ipconfig查看ip 地址,找到IPv4的ip地址,作为代码中的 ip 地址

5,新打开2个cmd

对应目录下运行,服务器和客户端代码👇

可以看到,第一次,ConnectionRefused,这时我们需要打开👇

网络共享 - Internet选项 - 连接 - 局域网设置 - 自动检测设置(✔)

Python报错:ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。_有无目标计算机积极拒绝,无法连接网络-CSDN博客

Client

Server

可是当我第2次TCP时,又拒绝连接,再次python运行才成功,也许有一定几率拒绝?👇

(2)代码

TCPClient.py

from socket import *
serverName = '192.168.15.1' # 本地IPv4地址,ipconfig得到
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_STREAM) # 建立TCP套接字,使用IPv4协议
clientSocket.connect((serverName,serverPort)) # 向服务器发起连接sentence = input('Input lowercase sentence:').encode() # 用户输入信息,并编码为bytes以便发送
clientSocket.send(sentence) # 将信息发送到服务器
modifiedSentence = clientSocket.recvfrom(1024) # 从服务器接收信息
print(modifiedSentence[0].decode()) # 显示信息
clientSocket.close() # 关闭套接字

TCPServer.py

from socket import *
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM) # 创建TCP欢迎套接字,使用IPv4协议
serverSocket.bind(('',serverPort)) # 将TCP欢迎套接字绑定到指定端口
serverSocket.listen(1) # 最大连接数为1
print("The server in ready to receive")while True:connectionSocket, addr = serverSocket.accept() # 接收到客户连接请求后,建立新的TCP连接套接字print('Accept new connection from %s:%s...' % addr)sentence = connectionSocket.recv(1024) # 获取客户发送的字符串capitalizedSentence = sentence.upper() # 将字符串改为大写connectionSocket.send(capitalizedSentence) # 向用户发送修改后的字符串connectionSocket.close() # 关闭TCP连接套接字

(3)详细解释

🎂服务器

1,关于端口号 port 

常用的端口号范围是从0到65535,其中0到1023是被保留给一些特定的服务(如HTTP的端口80、HTTPS的端口443等),而1024到65535是可供自由使用的端口范围

端口号用于标识特定的应用程序或服务

当您编写服务器端代码时,可以通过指定一个特定的端口号来监听客户端的连接请求

常见的做法是选择一个未被常用服务占用的端口号,例如12000、8080 

在服务器端代码中指定一个合适的端口号来监听连接请求,然后在客户端程序中使用相同的端口号来连接服务器。这样,客户端和服务器之间就可以通过指定的端口号进行通信

2, 详细流程

在目录 - 💧预习TCP - 🌼原理,进行回顾

3,

serverSocket = socket(AF_INET, SOCK_STREAM) # 创建TCP欢迎套接字,使用IPv4协议
  1. socket() 函数是用来创建套接字的系统调用。它接受两个参数:地址族(Address Family)和套接字类型(Socket Type)。

  2. AF_INET 参数指定了使用 IPv4 地址族,表示将使用 IPv4 地址来进行网络通信。

  3. SOCK_STREAM 参数指定了套接字的类型为流式套接字(TCP),它提供了可靠的、面向连接的、基于字节流的数据传输。

  4. serverSocket 是一个变量,用于存储创建的服务器端套接字

套接字,即 ip 地址和 端口号的整合。ip 地址标识主机,端口号表示应用程序或通信端口。

4, 

serverSocket.bind(('',serverPort)) # 将TCP欢迎套接字绑定到指定端口
  1. bind() 函数是用来将套接字绑定到一个特定的地址和端口号上的系统调用。它接受1个参数:IP 地址和端口号 的集合。

  2. '' 参数表示将服务器端套接字绑定到所有可用的网络接口上。这样,服务器就可以监听来自任何 IP 地址的客户端连接请求。

  3. serverPort 参数表示将服务器端套接字绑定到指定的端口号上

5,

connectionSocket, addr = serverSocket.accept() # 接收到客户连接请求后,建立新的TCP连接套接字
  1. connectionSocket:这是一个新创建的已连接套接字对象,它用于实际的数据传输。通过这个套接字,服务器可以与特定的客户端进行通信。服务器可以使用 connectionSocket 来发送和接收数据,以满足客户端的请求或提供服务。

  2. addr:这是客户端的地址信息,包含了客户端的 IP 地址和端口号。通常,它是一个元组,例如 (clientIP, clientPort)。通过获取客户端地址,服务器可以知道是哪个客户端发起了连接请求,可以根据需要记录日志、进行身份验证等操作

6, 

print('Accept new connection from %s:%s...' % addr)
  1. % 是字符串格式化操作符,用于将变量的值插入到字符串中的占位符位置。

  2. 'Accept new connection from %s:%s...' 是要打印的字符串,其中 %s 是占位符。

  3. % addr 是一个元组,在字符串中的 %s 占位符位置被 addr 中的值替换。addr 是客户端的地址信息,通常是一个包含客户端 IP 地址和端口号的元组。

  4. 打印结果将显示为类似于 Accept new connection from 192.168.0.1:5000... 的形式,其中 192.168.0.1 是客户端的 IP 地址,5000 是客户端的端口号

7,

sentence = connectionSocket.recv(1024) # 获取客户发送的字符串
  1. connectionSocket 是一个已连接的套接字对象,它用于与特定客户端进行通信。

  2. recv(1024) 是一个阻塞调用,它会从已连接套接字中接收最多 1024 字节的数据。如果客户端发送的数据量超过 1024 字节,则可能需要多次调用 recv() 来完整接收所有数据。

  3. setence 是一个变量,用于存储接收到的客户端数据(字符串)。

  4. 该行代码将等待,直到客户端发送数据或者客户端关闭连接。一旦有数据到达,它将被接收并存储在 setence 变量中

8,Client有connect(),而Server没有connect()的解释👇

  1. TCP Server:

    • TCP 服务器通常处于被动等待状态,它通过监听指定的端口,等待客户端的连接请求。
    • 一旦有客户端发送连接请求,服务器会接受该连接并创建一个新的套接字,即已连接套接字(Connected Socket)。
    • 已连接套接字与特定客户端建立了一对一的通信管道,可以进行双向的数据传输。
    • 在服务器端,已连接套接字用于与客户端进行通信,无需显式地调用 connect 方法。
  2. TCP Client:

    • TCP 客户端主动发起连接请求,它需要知道服务器的 IP 地址和端口号。
    • 客户端使用 connect 方法来连接到服务器指定的 IP 地址和端口。
    • connect 方法会在客户端和服务器之间建立一条连接,并返回一个已连接套接字。
    • 客户端通过已连接套接字与服务器进行通信,发送请求并接收响应

🎂客户端

1,

sentence = input('Input lowercase sentence:').encode() # 用户输入信息,并编码为bytes以便发送
  1. input('Input lowercase sentence:'):这是一个输入函数,它会在控制台中显示提示信息"Input lowercase sentence:"并等待用户输入。用户可以输入一个小写句子。

  2. 用户输入后,input 函数会返回用户输入的内容作为字符串。

  3. .encode():对返回的字符串进行编码操作。在这里,使用默认的UTF-8编码将字符串转换为字节序列。编码后的字节序列可以被网络传输或存储。

  4. 最终,编码后的字节序列被赋值给变量 sentence。现在,sentence 变量中存储的是用户输入的小写句子经过编码后的字节表示形式

2,将接收到的字节序列转换为字符串并在控制台中显示

print(modifiedSentence[0].decode()) # 显示信息
  1. modifiedSentence[0]:这是一个从 modifiedSentence 字节序列中获取第一个元素的操作。在网络通信中,通常会将接收到的数据作为字节序列进行处理,因此需要使用字节序列的索引来访问其中的元素。

  2. .decode():对字节序列进行解码操作。在这里,使用默认的UTF-8编码将字节序列转换为字符串。解码后的字符串可以在控制台中显示

🔥UDP套接字(实验2)

UDP连接比TCP少了个 监听 listen(),函数从 sent() 变成了 sendto(),建立的套接字是UDP的

🎂服务器

from socket import *
serverPort = 12000 # 自己指定的端口
serverSocket = socket(AF_INET, SOCK_DGRAM) # 使用IPv4协议,创建UDP套接字
serverSocket.bind(('', serverPort)) # 套接字绑定到指定端口
print('The server is ready to receive')
while True:message, clientAddress = serverSocket.recvfrom(2048) # 接受客户端信息,获取客户端地址modifiedMessage = message.upper() # 客户端发来的字符串变大写serverSocket.sendto(modifiedMessage, clientAddress) # 通过客户端地址,将字符串发送回客户端

🎂客户端

from socket import *
serverName = '192.168.15.1' # IPv4 的服务器地址
serverPort = 12000 # 人为指定的端口号
clientSocket = socket(AF_INET, SOCK_DGRAM) # 使用IPv4协议,创建UDP套接字
message = input('Input lowercase sentence:').encode() # 用户输入,并编码为bytes以便发送
clientSocket.sendto(message, (serverName, serverPort)) # 套接字发送到服务器
modifiedMessage, serverAddress = clientSocket.recvfrom(2048) # 从服务器接受字符串和地址
print(modifiedMessage.decode()) # 显示服务器返回的信息
clientSocket.close() 

效果和过程,与TCP类似

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

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

相关文章

设置Ubuntu 20.04的静态IP地址(wifi模式下)

一、引言 自己家用的Ubuntu的&#xff0c;重启后ip地址经常会改变&#xff0c;这个时候就需要我们手动配置静态IP了。 二、优点 给Ubuntu设置一个静态IP地址有以下几个好处&#xff1a; 持久性&#xff1a;静态IP地址是固定不变的&#xff0c;与设备的MAC地址绑定。这意味着…

【广州华锐视点】VR飞行员驾驶模拟实训系统

VR飞行员驾驶模拟实训系统是一种基于虚拟现实技术的航空装备仿真测试技术&#xff0c;可以用于飞行员、乘务员和机务人员的训练。该系统可以模拟真实的飞行环境&#xff0c;包括天气、地形、飞机性能等&#xff0c;使被试者能够在虚拟环境中进行飞行操作&#xff0c;从而提高其…

SSH安全登录远程主机

SSH服务器简介 SSH即Security SHell的意思&#xff0c;它可以将连线的封包进行加密技术&#xff0c;之后进行传输&#xff0c;因此相当的安全。 SSH是一种协议标准&#xff0c;其目的是实现安全远程登录以及其它安全网络服务。 SSH协定&#xff0c;在预设的状态下&#xff0c;…

11月14号|Move生态Meetup相约浪漫土耳其

Move是基于Rust编程语言&#xff0c;由Mysten Labs联合创始人兼CTO Sam Blackshear在Meta的Libra项目中开发而来&#xff0c;旨在为开发者提供比现有区块链语言更通用的开发语言。Sam的目标是创建Web3的JavaScript&#xff0c;即一种跨平台语言&#xff0c;使开发人员能够在多个…

C++设计模式_17_Mediator 中介者

Mediator 中介者也是属于“接口隔离”模式。 文章目录 1. 动机 (Motivation)2. 模式定义3. 结构(Structure)4. 要点总结5. 其他参考 1. 动机 (Motivation) 在软件构建过程中&#xff0c;经常会出现多个对象互相关联交互的情况&#xff0c;对象之间常常会维持一种复杂的引用关系…

HCIA数据通信——基础设备配置

想了想&#xff0c;为了方便回顾复习&#xff0c;将理论和实践结合起来才是正确的&#xff0c;不然一边理论&#xff0c;又单独做实验这样不方便。 因此之前的文章都删了&#xff0c;还是以华为从头开始吧&#xff01;实验与理论应用结合起来做。 一&#xff0c;查看设备信息 …

解密Kubernetes:探索开源容器编排工具的内核

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

【人脸检测 FPS 1000+】ubuntu下libfacedetection tensorrt部署

TensorRT系列之 Windows10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速…

《SpringBoot项目实战》第一篇—接口参数的一些弯弯绕绕

系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 本文参考项目源码地址&#xff1a;summo-springboot-interface-demo 前言 大家好&#xff01;…

Notepad++安装插件和配置快捷键

Notepad是一款轻量级、开源的文件编辑工具&#xff0c;可以编辑、浏览文本文件、二进制文件、.cpp、.java、*.cs等文件。Notepad每隔1个月&#xff0c;就有一个新版本&#xff0c;其官网是&#xff1a; https://github.com/notepad-plus-plus/notepad-plus-plus。这里介绍其插件…

Harmony 个人中心(页面交互、跳转、导航、容器组件)

个人中心 前言正文一、创建工程二、登录① 更换启动页面② 拓展修饰符③ 页面跳转④ 等待进度条 三、导航栏四、首页① 轮播图② 网格列表 五、我的① 带参数跳转 六、源码 前言 今天是1024&#xff0c;祝各位程序员们&#xff0c;钱多事少离家近&#xff0c;不秃也强bug黄。在…

mac系统u盘启动盘制作教程,更新至macOS Sonoma 14

mac系统怎么制作装系统的u盘,如果您要在多台电脑上安装 macOS&#xff0c;而又不想每次都下载安装器&#xff0c;这时可引导安装器就会很有用。一起来看苹果电脑u盘启动盘制作教程吧。 Macos系统安装包合集包揽macos 10.15&#xff0c;macos 11和苹果最新系统等多个版本 1、A…

H5游戏分享-全民找房祖名qmxzfzm

H5游戏分享-全民找房祖名qmxzfzm 一开始就比较简单 后面就会越来越难&#xff0c;而且也有时间限制 游戏的源码 <!DOCTYPE html> <html><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,ini…

嵌入式实时操作系统的设计与开发(消息)

消息 从概念上讲&#xff0c;消息机制和邮箱机制很类似&#xff0c;区别在于邮箱一般只能容纳一条消息&#xff0c;而消息则会包含一系列的消息。 系统定义了一个全局变量g_msgctr_header&#xff0c;通过它可以查找到任一已创建的消息容器。 每一个消息容器都可以根据其参数…

C++之左值、右值、std::forward、std::move总结(二百五十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Android Studio 导出 jar

AS版本&#xff1a;Android Studio Giraffe | 2022.3.1 Patch 1 1、File——New Module——Android Library 2、mylibrary——main——新建功能类 3、mylibrary——build.gradle——android {}内复制以下代码——Sync Now //Copy类型 tasks.register(makeJar, Copy) { //删…

react-高阶组件

一、什么是高阶组件 高阶组件&#xff08; Higher-Order Component&#xff0c;HOC &#xff09;是一个以组件作为参数&#xff0c;返回一个新组件的函数。 高阶组件最大的特点就是复用组件逻辑高阶组件本身并不是 React 的 API&#xff0c;而是React组件的一种设计模式&…

自动驾驶,从“宠儿”走进“淘汰赛”

从“一步到位”到场景、技术降维。从拼落地路径&#xff0c;到拼雷达、算力&#xff0c;再到如今的性价比之争&#xff0c;自动驾驶似乎变得愈发“接地气”。 作者|斗斗 编辑|皮爷 出品|产业家 比起去年&#xff0c;黄文欢和张放今年显得更加忙碌。 “自动驾驶赛道&…

windows下-mysql环境配置,以及使用navicat可视化数据库,便捷撰写sql语句。

文章目录 MySQL 连接到本地MySQL 下载MySQL连接基本SQL操作语句创建并查看数据库删除数据库修改数据库插入、删除、修改数据 图形化界面展示数据库 Navicat 基础操作连接本地的mysql数据库撰写sql语句 MySQL 连接到本地 MySQL 下载 直接系统自带应用商城下载&#xff0c;安装最…

MySQL 多表查询 事务 索引

目录 多表查询简介内连接查询 join on外连接查询 left join、right join子连接查询标量子查询列子查询 (in、not in)行子查询表子查询 多表查询案例 事务事务介绍操作 start transaction、commit、rollback事务四大特性(面试题) 索引索引介绍索引原理索引语法 index 上次学习了…