当前位置: 首页 > news >正文

TCP/IP 协议:网络世界的基石(2/10)

一、引言

在当今数字化时代,互联网已经成为人们生活中不可或缺的一部分。而在互联网的背后,TCP/IP 协议扮演着至关重要的角色,堪称互联网的基石。

TCP/IP 协议是一组用于数据通信的协议集合,它的名字来源于其中最重要的两个协议:传输控制协议(TCP)和网际协议(IP)。自 20 世纪 70 年代末期以来,TCP/IP 协议已经成为全球互联网通信的通用语言,它定义了数据如何在网络上进行传输和路由。

TCP/IP 协议遵循分层模型,将网络通信分为四个层次:链路层、网络层、传输层和应用层。每层负责不同的功能,通过协同工作,确保数据从源头安全、高效地传输到目的地。

链路层负责在物理媒介上发送和接收数据,如以太网、Wi-Fi 等。网络层负责数据包的路由和转发,确保数据包能够跨越多个网络到达目的地。IP 协议是这一层的核心,它通过给每个数据包分配一个唯一的 IP 地址,确保数据能够正确地路由到目标计算机。

传输层负责提供端到端的数据传输服务。TCP 和 UDP 是这一层的两个主要协议。TCP 是一种面向连接的、可靠的传输层协议,它确保数据包按顺序到达,并且允许接收方确认数据包的接收。UDP 则是一种无连接的、不可靠的传输层协议,它不保证数据包的顺序或完整性,但速度更快,适用于对实时性要求高的应用。

应用层为应用软件提供网络服务,如 HTTP、FTP、SMTP 等。这些协议定义了客户端和服务器之间的通信规则,使得用户能够在互联网上进行各种活动,如浏览网页、发送电子邮件、下载文件等。

总之,TCP/IP 协议是现代互联网通信的基础,它的重要地位不可替代。

二、TCP/IP 协议栈详细解释

(一)什么是计算机网络

计算机网络是根据应用的需要发展而来的,它是将地理位置分散的计算机系统和通信设备连接起来,实现资源共享和信息传递的系统。计算机网络的功能主要表现在硬件资源共享、软件资源共享和用户间信息交换三个方面。

硬件资源共享可以在全网范围内提供对处理资源、存储资源、输入输出资源等昂贵设备的共享,从而使用户节省投资,也便于集中管理和均衡分担负荷。软件资源共享使得互联网上的用户可以远程访问各类大型数据库,可以通过网络下载某些软件到本地机上使用,可以在网络环境下访问一些安装在服务器上的公用网络软件,也可以通过网络登录到远程计算机上使用该计算机上的软件,这样可以避免软件研制上的重复劳动以及数据资源的重复存储,也便于集中管理。用户间信息交换是计算机网络最基本的功能,主要完成计算机网络中各个节点之间的系统通信,用户可以在网上传送电子邮件、发布新闻消息、进行电子购物、电子贸易、远程电子教育等。

(二)TCP/IP 网络世界的规则

  1. OSI 参考模型具有简化相关的网络操作、提供设备间的兼容性和标准接口、促进标准化工作、结构上可以分隔易于实现和维护等优点。
  2. TCP/IP 协议栈可以看成是 OSI 参考模型的简化,分为四层:网络接入层、网络层、传输层、应用层。TCP/IP 协议栈与 OSI 参考模型存在一定的对应关系,应用层对应 OSI 模型的应用层、表示层和会话层;传输层对应 OSI 模型的传输层;网络层对应 OSI 模型的网络层;网络接入层对应 OSI 模型的数据链路层和物理层。
  3. TCP/IP 协议栈每一层的功能如下:
  • 网络接入层:位于 TCP/IP 协议栈的最底层,包括各种网络技术,如以太网、Wi-Fi 等,并处理数据帧的传输。它基本上包括了 ISO/OSI 模型中的数据链路层和物理层的所有功能,定义了如何利用网络来传送 IP 数据报,必须知道物理网络的各种细节,以便准确地格式化传输的数据,使其遵守网络规定。
  • 网络层:由互连网协议(IP)、互连网控制报文协议(ICMP)和互连网组管理协议(IGMP)等协议组成。IP 是 TCP/IP 的核心,也是网络互连层中最重要的协议,它提供基本的分组传送服务,定义数据报,定义 Internet 地址系统,把数据报分解或重组成易于在网络中传输的结构,在网络存取层和传输层之间传递数据,给远端主机的数据报指定路由,完成数据报的拥挤控制和信息控制。
  • 传输层:为应用层提供可靠的或不可靠的端到端服务。TCP(传输控制协议)是一种可靠的、面向连接的、字节流协议,利用端到端错误检测与纠正功能提供可靠的数据传输服务;UDP(用户数据报协议)是一个不可靠的无连接数据报协议,为应用程序提供低开销的无连接数据报传输服务。
  • 应用层:位于 TCP/IP 协议栈的顶层,为用户提供各种网络服务,如文件传输、远程登录、电子邮件等,同时包含与具体应用程序相关的所有细节。

(三)TCP/IP 模型的层间通信与数据封装

  1. 数据包在网络设备之间进行传输的过程中,为了保证数据包准确的发送到目的地,发送端会对数据包进行封装。在发送的数据包上附加 TCP 或者是 UDP 的包头形成数据段(segment),网络层会添加 IP 包头形成数据包(Packet),数据链路层会给数据添加以太网包头和 FCS 包尾,形成数据帧(Frame),最后转换成二进制的比特流通过物理线路传到接收方。这个操作过程就叫做数据封装,而对数据包进行处理时通信双方所遵循和协商好的规则称为协议。
  2. 接收端收到数据后会进行解封装,从物理层开始,进行与发送端相反的操作,一层层去掉包头,最终使应用层程序获取到数据信息,使得发送方和接收方数据通信完成。

(四)抓包了解数据结构

通过 Wireshark 抓取 HTTP 协议的报文,可以分析传输层、网络层和数据链路层封装的信息。

传输层封装的是 TCP 协议,可以看到源端口号,目标端口号。以访问百度为例,先通过三次握手建立连接,第一次握手:客户端发送 syn 包(syn=j)到服务器,并进入 SYN_SEND 状态,等待服务器确认;第二次握手:服务器收到 syn 包,必须确认客户的 SYN(ack=j+1),同时自己也发送一个 SYN 包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK (ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。

网络层封装的是 IP 包头,包括 IPV4 的版本,首部长度,协议类型是 TCP 协议,源 IP 地址,目标 IP 地址等。

数据链路层,协议类型是 OX0800 代表三层使用的是 IPV4 协议,源主机的 MAC 地址,目标主机的 MAC 地址等。

三、TCP/IP 各层功能和重要性

(一)应用层

  1. 列举应用层的各种协议,如文件传输类(HTTP、FTP、TFTP)、远程登录类(Telnet)、电子邮件类(SMTP)、网络管理类(SNMP)、域名解析类(DNS)等。
    • 文件传输类:
      • HTTP(超文本传输协议):适用于分布式超媒体信息系统,是 WWW 服务器使用的主要协议,允许用户在统一的界面下,采用不同的协议访问不同服务。
      • FTP(文件传输协议):用于简化 IP 网络上系统之间文件传输,用户可以高效从 Internet 上的 FTP 服务器下载大量的数据文件,实现资源共享和传递信息。FTP 包含控制连接和数据连接两种连接模式,控制连接用于传递用户端的命令和服务器端对命令的响应,使用服务器的 21 端口;数据连接用于传输文件和其他数据,如目录列表等,这种连接在需要数据传输时建立,每次使用的端口不一定相同,且数据连接既可能是服务器端发起,也可能是客户端发起。FTP 服务器数据连接有主动模式和被动模式,主动模式从服务器端向客户端发起连接,被动模式是客户端向服务器端发起连接。
      • TFTP(简单文件传输协议):是基于 UDP 的应用,对内存和处理器的要求很低,速度快,但功能不如 FTP 丰富,只能从文件服务器获得或写入文件,而不能列出目录,也不能进行认证,没有建立连接的过程及错误恢复的功能,适用范围不如 FTP 广泛。常见的应用例子是使用 TFTP 服务器来备份或恢复 Cisco 路由器、Catalyst 交换机的 IOS 镜像和配置文件。
    • 远程登录类:Telnet,通过一个终端登陆到其他服务器,建立在可靠的传输协议 TCP 之上。但 Telnet 协议所有数据(包括用户名和密码)均以明文形式发送,有潜在的安全风险,如今已被更安全的 SSH 协议所取代。
    • 电子邮件类:
      • SMTP(简单邮件传输协议):基于 TCP 协议,用来发送电子邮件。当用户发送邮件时,通过 SMTP 协议将邮件交给自己的邮箱服务器,邮箱服务器发现目标邮箱是其他服务器后,使用 SMTP 协议将邮件转发到目标邮箱服务器。
      • POP3/IMAP:邮件接收的协议,IMAP 协议相比于 POP3 更新,为用户提供的可选功能更多,几乎所有现代电子邮件客户端和服务器都支持 IMAP。
    • 网络管理类:SNMP(简单网络管理协议),允许第三方的管理系统集中采集来自许多网络设备的数据,为网络管理系统提供了底层网络管理的框架。利用 SNMP,一个管理工作站可以远程管理所有支持这种协议的网络设备,包括监视网络状态、修改网络设备配置、接收网络事件警告等。
    • 域名解析类:DNS(域名服务协议),基于 UDP,使用端口号 53。在浏览器中输入一个域名后,会有 DNS 服务器将域名解析为对应的 IP 地址。
  1. 分别介绍这些协议的作用,如 HTTP 是超文本传输协议,用于网页设计和数据传输等。
    • HTTP:主要是为 Web 浏览器与 Web 服务器之间的通信而设计,当使用浏览器浏览网页时,网页就是通过 HTTP 请求进行加载的。HTTP 协议基于 TCP 协议,发送 HTTP 请求之前首先要建立 TCP 连接,即经历三次握手。目前使用的 HTTP 协议大部分都是 1.1,在 1.1 的协议里,默认开启了 Keep-Alive,建立的连接可以在多次请求中被复用。HTTP 协议是 “无状态” 的协议,无法记录客户端用户的状态,一般通过 Session 来记录客户端用户的状态。
    • FTP:用于在 IP 网络上系统之间进行文件传输,用户可以高效下载或上传大量数据文件,实现资源共享和信息传递。FTP 服务器可以设置为公用、私有或两者兼之,用户可以为 FTP 帐号定义权限,访问特定区域。
    • TFTP:基于 UDP 的应用,对内存和处理器要求低,速度快,常用于备份或恢复网络设备的 IOS 镜像和配置文件。
    • Telnet:通过终端登录到其他服务器,进行远程操作。
    • SMTP:用于发送电子邮件,将用户写好的邮件交给邮箱服务器,由邮箱服务器转发到目标邮箱服务器。
    • POP3/IMAP:负责接收电子邮件,IMAP 协议功能更丰富,支持更多可选功能。
    • SNMP:为网络管理系统提供底层框架,管理工作站可以远程管理支持该协议的网络设备。
    • DNS:将域名解析为对应的 IP 地址,方便用户使用域名访问网站,而无需记住数字组成的 IP 地址。

(二)运输层

  1. 介绍运输层的主要协议 TCP 和 UDP 的特点和区别,如 TCP 是面向连接的可靠协议,UDP 是无连接的不可靠协议。
    • TCP(传输控制协议)是面向连接的协议,需要在传输数据之前建立连接。它是一种可靠的协议,可以保证数据包的可靠传输,确保数据在传输过程中不丢失、不乱序、不重复。当网络出现拥塞或丢包时,TCP 会进行流量控制和拥塞控制,根据网络状况调整发送速率,避免网络拥塞。TCP 的数据包结构相对复杂,包括头部和序列号等字段,采用字节流传输,保证数据按顺序到达接收方。TCP 只能是 1 对 1 的连接,首部较大为 20 字节。TCP 适用于要求数据传输可靠的场景,如文件传输、邮件等。
    • UDP(用户数据报协议)是无连接的协议,不需要建立连接,可以直接发送数据包。它是不可靠的协议,不保证数据包的可靠传输,可能会出现数据包丢失、重复、乱序等问题。UDP 不进行流量控制和拥塞控制,直接发送数据包,如果网络出现拥塞,UDP 数据包可能会丢失或延迟,甚至导致网络更加拥塞。UDP 的数据包结构相对简单,只包括源端口、目的端口、长度、校验和和数据等字段,采用数据报传输,不保证数据按顺序到达。UDP 适用于实时应用场景,如视频、音频、游戏等,对数据传输的实时性和延迟要求较高。UDP 支持 1 对 1、1 对多的连接。
  1. 详细解释 TCP 的可靠性实现方式,如三次握手建立连接和改进的三次握手断开连接。
    • 三次握手建立连接:
    • 第一次握手,客户端发送 syn 包(syn=j)到服务器,并进入 SYN_SEND 状态,等待服务器确认;
    • 第二次握手,服务器收到 syn 包,必须确认客户的 SYN(ack=j+1),同时自己也发送一个 SYN 包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;
    • 第三次握手,客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK (ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。
    • 改进的三次握手断开连接:当一方想要断开连接时,会发送 FIN 包表示结束数据传输,另一方收到 FIN 包后回复 ACK 确认,然后也发送 FIN 包表示自己也准备断开连接,最后发起方再回复 ACK 确认,完成连接断开。

(三)网络层

  1. 引入 IP 协议,解释其作用是制定新地址(IP 地址),以便区分两台主机是否同属一个网络。
    • IP 协议(Internet Protocol)是互联网中最基础的协议之一,负责在网络中寻址和路由数据包,将数据包从源主机传输到目标主机。它定义了数据包的格式、寻址方式和路由规则,是互联网通信的基础。IP 地址就是用来标识网络中的设备的地址,类似于现实生活中的门牌号码,通过 IP 地址可以唯一标识网络中的每个设备。IP 协议负责将数据包分割成适合网络传输的小块(分片),并在目标主机上将这些小块重新组合成完整的数据包(重组),以适应不同网络的传输需求,确保数据能够顺利传输到目标主机。IP 协议采用数据包交换的方式进行数据传输,将数据包从源主机传输到目标主机,而不需要建立专门的物理连接。IP 协议支持不同类型的网络,包括以太网、无线网络、广域网等,使得不同类型的网络能够互相通信和交换数据。
  1. 介绍网络层的其他协议,如 ARP 协议用于获取目标 MAC 地址,路由协议用于数据包的转发。
    • ARP(Address Resolution Protocol)协议用于获取目标 MAC 地址。当一个设备要向另一个设备发送数据时,如果只知道目标设备的 IP 地址,就需要通过 ARP 协议来获取目标设备的 MAC 地址。ARP 协议通过广播的方式发送请求,询问目标 IP 地址对应的 MAC 地址,目标设备收到请求后会回复自己的 MAC 地址。
    • 路由协议用于数据包的转发。路由器根据路由协议来确定数据包的转发路径,将数据包从一个网络转发到另一个网络。常见的路由协议有 OSPF、BGP 等。

(四)网络接口层

  1. 说明以太网协议对电信号进行分组并形成数据帧的过程。
    • 当以太网软件从网络层接收到数据报之后,需要根据需要把网际层的数据分解为较小的块,以符合以太网帧数据段的要求。以太网帧的整体大小必须在 64~1518 字节之间(不包含前导码)。有些系统支持更大的帧,最大可以支持 9000 字节。然后把数据块打包成帧,每一帧都包含数据及其他信息,这些信息是以太网网络适配器处理帧所需要的。最后把数据帧传递给对应于 OSI 模型物理层的底层组件,后者把帧转换为比特流,并且通过传输介质发送出去。
  1. 强调 MAC 地址的唯一性和以太网采用广播形式发送数据包的方式。
    • MAC 地址是 Media Access Control Address 的简称,由 IEEE 制定的一种网络通信协议,用以确定网络上各节点的位置。MAC 地址是用来标识网络设备唯一性的,它是一个网络层协议,可以用于确定设备通信的传输介质和节点。MAC 地址长度为 48 位,及 6 个字节,一般用 16 进制数字加上冒号的形式来表示。在网卡出厂时就确定了,不能修改,通常是唯一的(虚拟机中的 MAC 地址不是真实的 MAC 地址,可能会冲突;也有些网卡支持用户配置 MAC 地址)。
    • 以太网采用广播形式发送数据包。当一个设备发送数据时,会将数据帧中的目的 MAC 地址设置为目标设备的 MAC 地址,然后将数据帧发送到网络中。网络中的其他设备接收到数据帧后,会检查其中的目的 MAC 地址。如果目的 MAC 地址与自己的 MAC 地址相匹配,适配器软件就会处理接收到的帧,把数据传递给协议栈中较高的层;如果目的 MAC 地址与自己的 MAC 地址不匹配,设备就会丢弃该数据帧。

四、TCP/IP 协议的实际应用案例

(一)文件传输案例

  1. 介绍使用 Java 中的 Socket 通信基于 TCP/IP 协议进行文件传输的案例。

Java 中可以使用ServerSocket和Socket类实现基于 TCP/IP 协议的文件传输。服务端创建一个ServerSocket对象,绑定到指定端口,等待客户端的连接请求。客户端创建一个Socket对象,指定服务端的 IP 地址和端口,发出连接请求。连接建立后,客户端通过文件输入流读取本地文件,然后通过Socket的输出流向服务端发送文件数据。服务端通过Socket的输入流接收文件数据,并保存到本地文件中。

  1. 展示服务端和客户端的代码示例,解释文件传输的过程。

服务端代码:

   import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;public class TCPServer {public static void main(String[] args) throws IOException {// 获取 ServerSocket 对象,提供 TCP 连接服务ServerSocket serverSocket = new ServerSocket(8888);// 等待接收客户端的 TCP 连接申请Socket socket = serverSocket.accept();// 保存客户端发送的文件// 获取 TCP 连接提供的字节输入流InputStream is = socket.getInputStream();// 把数据存入指定文件FileOutputStream fos = new FileOutputStream(new File("D://receivedFile.txt"));byte[] b = new byte[1024];int len;// 读取数据,保存数据while ((len = is.read(b))!= -1) {fos.write(b, 0, len);}// 关闭资源fos.close();is.close();socket.close();serverSocket.close();}}

客户端代码:

   import java.io.FileInputStream;import java.io.IOException;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;public class TCPClient {public static void main(String[] args) throws IOException {// 创建了一个匿名的 InetAddress 独享,创建了一个 socket,进行连接Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 8888);// 创建输出流,用来发送字节流OutputStream os = socket.getOutputStream();// 本身我需要获取到本地的一个文件,所以我需要 inputFileInputStream fis = new FileInputStream(new File("D://originalFile.txt"));// 具体读和写的过程byte[] buffer = new byte[1024];int len;while ((len = fis.read(buffer))!= -1) {// 再次提醒这样是为了防止读取到重复数据os.write(buffer, 0, len);}// 关闭资源fis.close();os.close();socket.close();}}

文件传输过程:首先服务端创建一个ServerSocket对象并绑定到指定端口,然后进入等待状态,等待客户端的连接请求。客户端创建一个Socket对象,指定服务端的 IP 地址和端口,发出连接请求。当服务端接收到客户端的连接请求后,建立连接,服务端通过accept()方法返回一个Socket对象。接着,客户端通过文件输入流读取本地文件,并通过Socket的输出流向服务端发送文件数据。服务端通过Socket的输入流接收文件数据,并保存到本地文件中。

(二)Python 通信案例

  1. 使用 Python 实现 TCP/IP 协议通信的示例,包括服务器端和客户端的代码。

服务器端代码:

import socketimport threading# 创建一个 socket 对象serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 获取本地主机名host = socket.gethostname()# 设置端口号port = 9999# 绑定端口号serversocket.bind((host, port))# 设置最大连接数,超过后排队serversocket.listen(5)client_list = []# 用于存储所有连接的客户端 socketdef handle_client(clientsocket):data = clientsocket.recv(1024).decode()print(f"收到数据:{data}")clientsocket.send("已收到您的消息".encode())clientsocket.close()client_list.remove(clientsocket)while True:# 建立客户端连接clientsocket, addr = serversocket.accept()print(f"连接地址:{str(addr)}")client_list.append(clientsocket)# 为每个新连接创建一个线程来处理threading.Thread(target=handle_client, args=(clientsocket,)).start()

客户端代码:

import socket# 创建一个 socket 对象s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 获取本地主机名host = socket.gethostname()# 设置端口号port = 9999# 连接服务,指定主机和端口s.connect((host, port))# 发送数据s.send("Hello, server".encode())# 接收响应数据response = s.recv(1024).decode()print(f"收到响应:{response}")# 关闭连接s.close()

  1. 扩展功能的介绍,如多用户支持、消息广播、客户端身份验证和持久化连接等。
    • 多用户支持:服务器现在可以同时处理多个客户端的连接。通过使用线程或异步编程,可以为每个新连接的客户端创建一个独立的处理线程或任务,从而实现多用户支持。
    • 消息广播:服务器可以将消息广播给所有连接的客户端。可以创建一个函数,遍历所有连接的客户端并发送消息。例如:
def broadcast_message(message):for client in client_list:client.send(message.encode())

  • 客户端身份验证:服务器可以对客户端进行身份验证,只有通过验证的客户端才能发送消息。在handle_client函数中添加一个验证步骤,例如要求客户端在连接时发送一个特定的令牌或用户名,然后服务器可以检查该令牌或用户名是否有效。如果验证失败,服务器可以关闭连接或拒绝接收消息。
  • 持久化连接:服务器和客户端可以保持连接打开,以便于连续通信。可以使用长轮询或心跳机制来保持连接打开。这意味着服务器和客户端应该定期发送消息以保持连接活动状态。如果服务器或客户端在一段时间内没有收到消息,它们可以认为连接已断开并采取适当的行动。

(三)公共聊天室案例

  1. 功能说明,如服务端设定客户端连接个数上限,客户端可与服务端单独通信。

公共聊天室的服务端可以设定客户端连接个数上限,当达到上限时,新的客户端连接将被拒绝。客户端可以向服务端发送消息,服务端可以将消息广播给所有连接的客户端,客户端也可以接收服务端广播的消息。同时,客户端可以与服务端单独通信,即客户端发送给服务端的消息只有服务端可以看到,服务端回复的消息也只有发送消息的客户端可以看到。

  1. 展示服务端和客户端的代码,解释公共聊天室的实现过程。

服务端代码:

   // MyServer.cpp : 定义控制台应用程序的入口点。#include "stdafx.h"#include <iostream>#include <stdlib.h>#include <winsock2.h>// 引用头文件#pragma comment(lib,"ws2_32.lib")// 最大连接数#define g_MaxConnect 20int g_Connect = 0;struct sock_params {SOCKET hsock;int nSockIndex;};// 线程实现函数DWORD WINAPI threadpro(LPVOID pParam) {sock_params* sockPam = (sock_params*)pParam;SOCKET hsock = sockPam->hsock;int nSockIndex = sockPam->nSockIndex;char aIndex[4];_itoa_s(nSockIndex, aIndex, 10);char buffer[1024];char sendBuffer[1024];if (hsock!= INVALID_SOCKET) {std::cout << "客户端 " << nSockIndex << " 加入服务器!" << std::endl;}while (1) {// 循环接收发送的内容int num = recv(hsock, buffer, 1024, 0);// 阻塞函数,等待接收内容if (num > 0) {std::cout << "客户端 " << nSockIndex << ": " << buffer << std::endl;memset(sendBuffer, 0, 1024);char strValue[30] = "服务器 ";strcat_s(strValue, aIndex);strcpy_s(sendBuffer, strValue);char strSpace[30] = " 收到数据如下: ";strcat_s(sendBuffer, strSpace);strcat_s(sendBuffer, buffer);int ires = send(hsock, sendBuffer, sizeof(sendBuffer), 0);// 回送消息// cout << "Send to Client: " << sendBuffer << endl;}else {std::cout << "客户端 " << nSockIndex << " 关闭!" << std::endl;// cout << "Server Process " << nSockIndex << " Closed" << endl;return 0;}}return 0;}// 主函数void main() {WSADATA wsd;// 定义 WSADATA 对象WSAStartup(MAKEWORD(2, 2), &wsd);SOCKET m_SockServer;sockaddr_in serveraddr;sockaddr_in serveraddrfrom;SOCKET m_Server[g_MaxConnect];serveraddr.sin_family = AF_INET;// 设置服务器地址serveraddr.sin_port = htons(4600);// 设置端口号serveraddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");m_SockServer = socket(AF_INET, SOCK_STREAM, 0);int nStatus = bind(m_SockServer, (sockaddr*)&serveraddr, sizeof(serveraddr));if (nStatus == 0) {std::cout << "服务端启动成功!" << std::endl;}else {std::cout << "服务端启动失败!" << std::endl;return;}int iLisRet = 0;int len = sizeof(sockaddr);while (1) {iLisRet = listen(m_SockServer, 0);// 进行监听m_Server[g_Connect] = accept(m_SockServer, (sockaddr*)&serveraddrfrom, &len);// 同意连接if (m_Server[g_Connect]!= INVALID_SOCKET) {if (g_Connect > g_MaxConnect - 1) {char WarnBuf[50] = "客户端连接个数:超限!";int ires = send(m_Server[g_Connect], WarnBuf, sizeof(WarnBuf), 0);}else {char cIndex[4];_itoa_s(g_Connect, cIndex, 10);char buf[50] = "你的服务端 ID: ";strcat_s(buf, cIndex);int ires = send(m_Server[g_Connect], buf, sizeof(buf), 0);// 发送字符过去// cout << buf << endl;HANDLE m_Handel;// 线程句柄DWORD nThreadId = 0;// 线程 IDsock_params sockPam;sockPam.hsock = m_Server[g_Connect];sockPam.nSockIndex = g_Connect;m_Handel = (HANDLE)::CreateThread(NULL, 0, threadpro, &sockPam, 0, &nThreadId);CloseHandle(m_Handel);}++g_Connect;}}WSACleanup();}

客户端代码:

   // MyClient.cpp : 定义控制台应用程序的入口点。#include "stdafx.h"#include <iostream>#include <stdlib.h>#include <stdio.h>#include "winsock2.h"#include <time.h>#pragma comment(lib,"ws2_32.lib")void main() {WSADATA wsd;// 定义 WSADATA 对象WSAStartup(MAKEWORD(2, 2), &wsd);SOCKET m_SockClient;sockaddr_in clientaddr;clientaddr.sin_family = AF_INET;// 设置服务器地址clientaddr.sin_port = htons(4600);// 设置服务器端口号clientaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");m_SockClient = socket(AF_INET, SOCK_STREAM, 0);if (m_SockClient == INVALID_SOCKET) {printf("Sock 初始化失败: %d\n", WSAGetLastError());WSACleanup();return;}// 获取发送缓冲区和接送缓冲区大小{int optlen = 0;int optval = 0;optlen = sizeof(optval);getsockopt(m_SockClient, SOL_SOCKET, SO_SNDBUF, (char*)&optval, &optlen);printf("send buf len is %d\n", optval);// 64 位 默认发送缓冲区 64kgetsockopt(m_SockClient, SOL_SOCKET, SO_RCVBUF, (char*)&optval, &optlen);printf("Recv buf len is %d\n", optval);// 64 位 默认接收缓冲区 64k}// 设定发送缓冲区大小// optval = 1024 * 2;  // setsockopt(ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&optval, optlen);int nSuccess = connect(m_SockClient, (sockaddr*)&clientaddr, sizeof(clientaddr));// 连接超时if (nSuccess == 0) {std::cout << "连接服务器成功!" << std::endl;}else {std::cout << "连接服务器失败!" << std::endl;return;}char buffer[1024];char inBuf[1024];int num = 0;num = recv(m_SockClient, buffer, 1024, 0);// 阻塞if (num > 0) {std::cout << buffer << std::endl;char* pResult = strstr(buffer, "超限");if (pResult!= NULL) {std::cout << "服务器连接个数超限,不可用!" << std::endl;system("pause");return;}while (1) {std::cout << "请输入要发送的消息:" << std::endl;std::cin >> inBuf;if (strcmp(inBuf, "exit") == 0) {send(m_SockClient, inBuf, sizeof(inBuf), 0);// 发送退出指令return;}int send_len = send(m_SockClient, inBuf, sizeof(inBuf), 0);if (send_len < 0) {std::cout << "发送失败!请检查服务器是否开启!" << std::endl;system("pause");return;}int recv_len = recv(m_SockClient, buffer, 1024, 0);// 接收客户端发送过来的数据if (recv_len >= 0) {std::cout << buffer << std::endl;}}}}

公共聊天室的实现过程:服务端首先初始化WSADATA对象,创建一个SOCKET对象并绑定到指定的端口号。然后,服务端进入一个无限循环,监听来自客户端的连接请求。当一个客户端请求连接时,服务端接受请求并创建一个新的SOCKET对象来与该客户端通信。服务端为每个连接的客户端创建一个线程来处理通信,线程函数接收客户端发送的消息,并将消息加上服务器的标识后回送给客户端。如果客户端关闭连接,线程函数退出。服务端还可以设置客户端连接个数上限,当达到上限时,新的客户端连接将被拒绝。客户端首先初始化WSADATA对象,

五、结论

TCP/IP 协议作为互联网的基石,其重要性不言而喻。从分层模型来看,各层功能明确且相互协作,共同确保了数据在网络中的高效、准确传输。

应用层的众多协议为用户提供了丰富多样的网络服务,无论是文件传输、远程登录、电子邮件还是网络管理和域名解析,都极大地满足了人们在互联网时代的各种需求。这些协议的存在使得用户能够轻松地进行各种网络活动,实现资源共享和信息交流。

运输层的 TCP 和 UDP 协议各具特点,满足了不同应用场景的需求。TCP 的可靠性保证了数据传输的准确性和完整性,适用于对数据传输质量要求较高的场景;而 UDP 的高效性则使其在实时性要求高的应用中发挥了重要作用。

网络层的 IP 协议通过制定新地址,确保了两台主机能够准确区分彼此,并实现跨网络的数据传输。ARP 协议和路由协议的协同作用,使得数据包能够顺利地找到目标主机并进行转发。

网络接口层的以太网协议对电信号进行分组并形成数据帧,同时 MAC 地址的唯一性和以太网的广播形式确保了数据在局域网内的正确传输。

TCP/IP 协议的实际应用案例进一步展示了其强大的功能和灵活性。文件传输案例中,Java 和 Python 实现的基于 TCP/IP 协议的文件传输,为用户提供了高效的数据传输方式。Python 通信案例中的多用户支持、消息广播、客户端身份验证和持久化连接等扩展功能,丰富了网络通信的应用场景。公共聊天室案例则展示了 TCP/IP 协议在实现多人实时通信方面的能力。

总之,TCP/IP 协议的重要性不仅在于其作为互联网通信的基础,更在于其各层功能的协同作用和实际应用中的广泛适用性。它为我们的数字生活提供了坚实的支撑,推动了互联网技术的不断发展和进步。

相关文章推荐:

1、计算机网络基础全攻略:探秘网络构建块(1/10)

相关文章:

TCP/IP 协议:网络世界的基石(2/10)

一、引言 在当今数字化时代&#xff0c;互联网已经成为人们生活中不可或缺的一部分。而在互联网的背后&#xff0c;TCP/IP 协议扮演着至关重要的角色&#xff0c;堪称互联网的基石。 TCP/IP 协议是一组用于数据通信的协议集合&#xff0c;它的名字来源于其中最重要的两个协议…...

小R的二叉树探险 | 模拟

问题描述 在一个神奇的二叉树中&#xff0c;结构非常独特&#xff1a; 每层的节点值赋值方向是交替的&#xff0c;第一层从左到右&#xff0c;第二层从右到左&#xff0c;以此类推&#xff0c;且该二叉树有无穷多层。 小R对这个二叉树充满了好奇&#xff0c;她想知道&#xf…...

Redis ⽀持哪⼏种数据类型?适⽤场景,底层结构

目录 Redis 数据类型 一、String&#xff08;字符串&#xff09; 二、Hash&#xff08;哈希&#xff09; 三、List&#xff08;列表&#xff09; 四、Set&#xff08;集合&#xff09; 五、ZSet(sorted set&#xff1a;有序集合) 六、BitMap 七、HyperLogLog 八、GEO …...

十、事件类型(鼠标事件、焦点.. 、键盘.. 、文本.. 、滚动..)、事件对象、事件流(事件捕获、事件冒泡、阻止冒泡和默认行为、事件委托)

1. 事件类型 1.1 鼠标事件 1.1.1 click 鼠标点击 1.1.2 mouseenter 鼠标进入 1.1.3 mouseleave 鼠标离开 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widt…...

RabbitMQ学习-One

同步调用和异步调用 1.假设我们现在又两个服务&#xff0c;分别是修改商品服务和查询商品服务&#xff0c;每个服务都有自己的数据库&#xff1b; 2.左侧的流程假设我们总共需要耗时40ms&#xff1b; 3.因为不同服务数据库不一样&#xff0c;所以我们就要考虑修改了左边服务的…...

蓝队基础,网络七杀伤链详解

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…...

机器学习实战:银行客户是否认购定期存款

项目结构与步骤 1. 项目概述 项目名称&#xff1a;葡萄牙银行电话营销活动分析与定期存款认购预测目标&#xff1a;通过分析银行的电话营销数据&#xff0c;构建模型预测客户是否会认购定期存款。数据来源&#xff1a;葡萄牙银行营销活动数据集关键挑战&#xff1a;数据不平衡…...

【一篇搞定配置】网络分析工具WireShark的安装与入门使用

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;各种软件安装与配置_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1.…...

气膜场馆照明设计:科技与环保的完美结合—轻空间

气膜场馆的照明设计&#xff0c;选用高效节能的400瓦LED灯具&#xff0c;结合现代节能技术&#xff0c;提供强大而均匀的光照。LED灯具在光效和寿命方面优势显著&#xff0c;不仅降低运营能耗&#xff0c;还有效减少碳排放&#xff0c;为绿色场馆建设贡献力量。 科学分布&…...

C语言程序编译和链接

编译环境和运行 编译环境也可以称为翻译环境&#xff0c;是将源代码转换为机器可以识别的二进制指令&#xff1b; 运行环境也可以称为执行环境&#xff0c;用于实际执行代码&#xff1b; 翻译环境 翻译环境由编译和链接两个部分组成&#xff0c;而编译又可以分解为&#x…...

springBoot整合 Tess4J实现OCR识别文字(图片+PDF)

1. 环境准备 JDK 8 或更高版本Maven 3.6 或更高版本Spring Boot 2.4 或更高版本Tesseract OCR 引擎Tess4J 库 2. 安装 Tesseract OCR 引擎 下载地址&#xff1a; Home UB-Mannheim/tesseract Wiki GitHub linux直接安装&#xff1a;sudo apt-get install tesseract-ocr 3.…...

阿里数字人工作 Emote Portrait Alive (EMO):基于 Diffusion 直接生成视频的数字人方案

TL;DR 2024 年 ECCV 阿里智能计算研究所的数字人工作&#xff0c;基于 diffusion 方法来直接的从音频到视频合成数字人&#xff0c;避免了中间的三维模型或面部 landmark 的需求&#xff0c;效果很好。 Paper name EMO: Emote Portrait Alive - Generating Expressive Portra…...

Java将PDF保存为图片

将 PDF 文件转换为图片是常见的需求之一&#xff0c;特别是在需要将 PDF 内容以图像形式展示或处理时。其中最常用的是 Apache PDFBox。 使用 Apache PDFBox Apache PDFBox 是一个开源的 Java 库&#xff0c;可以用来处理 PDF 文档。它提供了将 PDF 页面转换为图像的功能。 …...

医药企业的终端市场营销策略

近年来&#xff0c;随着医药行业的快速发展&#xff0c;终端市场逐渐成为企业竞争的关键领域。在政策趋严、市场环境变化以及数字化转型的大背景下&#xff0c;医药企业如何在终端市场中立于不败之地&#xff1f;本文结合我们在医药数字化领域的经验&#xff0c;为大家剖析终端…...

使用EFK收集k8s日志

首先我们使用EFK收集Kubernetes集群中的日志&#xff0c;本次实验讲解的是在Kubernetes集群中启动一个Elasticsearch集群&#xff0c;如果企业内已经有了Elasticsearch集群&#xff0c;可以直接将日志输出至已有的Elasticsearch集群。 文章目录 部署elasticsearch创建Kibana创建…...

Vue3 + TypeScript 项目搭建

Vue3 TypeScript 项目搭建 环境准备 首先确保你的开发环境满足以下要求&#xff1a; # 检查 Node.js 版本 (需要 14.0 或更高版本) node -v# 检查 npm 版本 npm -v# 安装或更新 Vue CLI npm install -g vue/cli创建项目 使用 Vue CLI 创建项目&#xff1a; # 创建项目 np…...

Python操作neo4j库py2neo使用(一)

Python操作neo4j库py2neo使用&#xff08;一&#xff09; 安装&#xff08;只用于测试&#xff09; docker-compose .yml 文件 version: 3.8 services:neo4j:image: neo4j:5.6.0-enterprise #商业版镜像hostname: neo4jcontainer_name: neo4jports:- "7474:7474"-…...

(原创)Android Studio新老界面UI切换及老版本下载地址

前言 这两天下载了一个新版的Android Studio&#xff0c;发现整个界面都发生了很大改动&#xff1a; 新的界面的一些设置可参考一些博客&#xff1a; Android Studio新版UI常用设置 但是对于一些急着开发的小伙伴来说&#xff0c;没有时间去适应&#xff0c;那么怎么办呢&am…...

Linux——用户级缓存区及模拟实现fopen、fweite、fclose

linux基础io重定向-CSDN博客 文章目录 目录 文章目录 什么是缓冲区 为什么要有缓冲区 二、编写自己的fopen、fwrite、fclose 1.引入函数 2、引入FILE 3.模拟封装 1、fopen 2、fwrite 3、fclose 4、fflush 总结 前言 用快递站讲述缓冲区 收件区&#xff08;类比输…...

CKA认证 | Day2 K8s内部监控与日志

第三章 Kubernetes监控与日志 1、查看集群资源状态 在 Kubernetes 集群中&#xff0c;查看集群资源状态和组件状态是非常重要的操作。以下是一些常用的命令和解释&#xff0c;帮助你更好地管理和监控 Kubernetes 集群。 1.1 查看master组件状态 Kubernetes 的 Master 组件包…...

大模型部署,运维,测试所需掌握的知识点

python环境部署: python3 -m site --user-base 返回用户级别的Python安装基础目录 sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 将python3的默认路径/usr/bin/python3替…...

JDBC编程---Java

目录 一、数据库编程的前置 二、Java的数据库编程----JDBC 1.概念 2.JDBC编程的优点 三.导入MySQL驱动包 四、JDBC编程的实战 1.创造数据源&#xff0c;并设置数据库所在的位置&#xff0c;三条固定写法 2.建立和数据库服务器之间的连接&#xff0c;连接好了后&#xff…...

什么是沙箱(Sandbox)技术

沙箱技术是一种重要的计算机安全机制&#xff0c;主要用于隔离程序运行环境&#xff0c;以防止恶意代码或应用程序对系统和数据造成破坏。通过限制代码的访问权限和行为&#xff0c;沙箱为程序提供了一个受控且隔离的执行环境。 核心特点 隔离性沙箱运行的程序被限制在一个受控…...

TCP socket api详解

文章目录 netstat -nltpaccept简单客户端工具 telnet 指定服务连接connect异常处理version 1 单进程版version 2 多进程版version 3 -- 多线程版本version 4 ---- 线程池版本 创建套接字socket sockaddr_in结构体 bind 之后就和UDP不一样了。 因为TCP是一个面向连接的服务器&…...

Linux——环境变量

环境变量一般指的是在操作系统重用来指定操作系统运行环境的一些参数&#xff0c;这些参数会被bash使用&#xff0c;而bash是被我们用户使用的&#xff0c;也就是说&#xff0c;这些环境变量间接的也是被我们用户使用的。环境变量通常都有某些特殊的用途&#xff0c;它在系统重…...

Windows Pycharm 远程 Spark 开发 PySpark

一、环境版本 环境版本PyCharm2024.1.2 (Professional Edition)Ubuntu Kylin16.04Hadoop3.3.5Hive3.1.3Spark2.4.0 二、Pycharm远程开发 文件-远程-开发 选择 SSH连接&#xff0c;连接虚拟机&#xff0c;选择项目目录即可远程开发...

【es6进阶】vue3中的数据劫持的最新实现方案的proxy的详解

vuejs中实现数据的劫持,v2中使用的是Object.defineProperty()来实现的&#xff0c;在大版本v3中彻底重写了这部分&#xff0c;使用了proxy这个数据代理的方式&#xff0c;来修复了v2中对数组和对象的劫持的遗留问题。 proxy是什么 Proxy 用于修改某些操作的默认行为&#xff0…...

【Isaac Sim】加载自带模型或示例时报 Isaac Sim is not responding

Isaac Sim对电脑配置要求很高&#xff0c;开机第一次打开 Isaac Sim 时&#xff0c;直接就报 Isaac Sim is not responding 卡死了&#xff0c;这是由于第一次需要加载一些资源&#xff0c;耗时会导致 Isaac Sim 无响应&#xff0c;这里等一会会自动给回复。 加载自带模型或示…...

React (三)

文章目录 项目地址十二、性能优化12.1 使用useMemo避免不必要的计算12.2 使用memo缓存组件,防止过度渲染12.3 useCallBack缓存函数12.4 useCallBack里访问之前的状态(没懂)十三、Styled-Components13.1 安装13.2给普通html元素添加样式13.3 继承和覆盖样式13.4 给react组件添…...

C0031.在Clion中使用mingw编译器来编译opencv的配置方法

mingw编译器编译opencv库的配置方法...

多目标跟踪算法

文章目录 一、传统方法1. 基于卡尔曼滤波器的方法1.1 Kalman Filter(卡尔曼滤波器) 2. 基于数据关联的方法2.1 匈牙利算法 二、深度学习方法1. 基于检测的多目标跟踪1.1 SORT算法1.2 DeepSort1.3 BoT-SORT 2. 基于特征关联和增强的方法2.1 ByteTrack 3. 基于Transformer的方法3…...

【CSS in Depth 2 精译_059】9.2 把 CSS 模块组合成更大的结构

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 【第九章 CSS 的模块化与作用域】 ✔️ 9.1 模块的定义 9.1.1 模块和全局样式9.1.2 一个简单的 CSS 模块9.1.3 模块的变体9.1.4 多元素模块 9.2 将模块组合为更大的结构 ✔️ 9.2.1 模块中多个职责的…...

uniapp+vue3+ts H5端使用Quill富文本插件以及解决上传图片反显的问题

uniappvue3ts H5端使用Quill富文本插件以及解决上传图片反显的问题 1.在项目中安装Quill npm i quill1.3.72.需要显示富文本的页面完整代码 <template><view><div ref"quillEditor" style"height: 65vh"></div></view> &…...

shell(二)

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…...

在使用PCA算法进行数据压缩降维时,如何确定最佳维度是一个关键问题?

一、PCA算法的基本原理 PCA算法的核心思想是通过正交变换&#xff0c;将一组可能相关的变量转换成一组线性不相关的变量&#xff0c;称为主成分。这组主成分能够以最小的信息损失来尽可能多地保留原始数据集的变异性。具体来说&#xff0c;PCA算法包括以下几个步骤&#xff1a…...

学习嵩山版《Java 开发手册》:编程规约 - 命名风格(P1 ~ P2)

概述 《Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结&#xff0c;他旨在提升开发效率和代码质量 《Java 开发手册》是一本极具价值的 Java 开发规范指南&#xff0c;对于提升开发者的综合素质和代码质量具有重要意义 学习《Java 开发手册》是一个提升 Jav…...

#渗透测试#红蓝攻防#HW#SRC漏洞挖掘01之静态页面渗透

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…...

开源POC库推荐

声明 学习视频来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…...

深度学习每周学习总结J6(ResNeXt-50 算法实战与解析 - 猴痘识别)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 0. 总结ResNeXt基本介绍 1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数&#xff1a;定义损失函数&…...

用vite下载的react + TS的项目,组件会调用两次

解决方案: 去掉main.tsx文件中的StrictMode...

STM32F4----DCA数字量转换成模拟量

STM32F4----DCA数字量转换成模拟量 基本原理 上一节讲诉了ADC的具体原理与程序搭建https://blog.csdn.net/qq_35970934/article/details/143999874?spm1001.2014.3001.5501。这节讲DAC的原理和程序&#xff0c;在实际应用中&#xff0c;我们经常需要调节电压的输出大小&…...

springboot3如何集成knife4j 4.x版本及如何进行API注解

1. 什么是Knife4j knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案, 取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍!knife4j的前身是swagger-bootstrap-ui,swagger-bootstrap-ui自1.9.6版本后,正式更名为knife4j为了契合微服务的架构发展,由于原来…...

【Linux网络 (二)】套接字编程

Linux: 网络 一、前言二、端口号 (port)1&#xff09;port、套接字概念2&#xff09;端口号 vs 进程id3&#xff09;端口号和进程关系 三、认识TCP/Udp协议1&#xff09;连接性解释2&#xff09;可靠性解释3&#xff09;面向数据报/字节流解释 四、网络字节序五、struct sockad…...

SQL 语句执行计划中的连接方式

SQL 语句执行计划中的连接方式 join操作 join操作基本分为3大类&#xff1a;外连接&#xff08;细分为&#xff1a;左连接&#xff08;Left outer join/ left join&#xff09;、右连接&#xff08;right outer join/ right join&#xff09;、全连接&#xff08;full outer …...

3、集线器、交换机、路由器、ip的关系。

集线器、交换机、路由器三者的关系 1、集线器2、交换机&#xff08;每个交换机是不同的广播域&#xff0c;ip地址起到划分广播域的作用&#xff09;3、 路由器4、ip地址 1、集线器 一开始两台电脑通信就需要网线就可以&#xff0c;但是三台或者更多主机通信时&#xff0c;就需…...

OpenCV相机标定与3D重建(3)校正鱼眼镜头畸变的函数calibrate()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::fisheye::calibrate 函数是 OpenCV 中用于校正鱼眼镜头畸变的一个重要函数。该函数通过一系列棋盘格标定板的图像来计算相机的内参矩阵和畸变…...

【论文笔记】LLaVA-KD: A Framework of Distilling Multimodal Large Language Models

Abstract 大语言模型(Large Language Models, LLM)的成功&#xff0c;使得研究者为了统一视觉和语言的理解去探索多模态大预言模型(Multimodal Large Language Models, MLLM)。 但是MLLM庞大的模型和复杂的计算使其很难应用在资源受限的环境&#xff0c;小型MLLM(s-MLLM)的表现…...

C++内存管理和模板

文章目录 1. C内存管理1.1 new1.1.1 内置类型1.1.2 自定义类型1.1.3 定位new表达式1.1.4 new的优势与不足1.1.5 new的原理 1.2 delete1.2.1 内置类型1.2.2 自定义类1.2.3 delete和free1.2.4 delete原理 1.3 new和delete的对应1.3.1 内置类型1.3.2 自定义类型 2. 模板2.1 函数模…...

Docker 容器化开发 应用

Docker 常用命令 存储 - 目录挂载 存储 卷映射 自定义网络 Docker Compose语法 Dockerfile - 制作镜像 镜像分层机制 完结...

element-plus教程:Input Number 数字输入框

一、基础用法 要使用Input Number数字输入框&#xff0c;只需要在<el-input-number>元素中使用v-model绑定变量即可。例如&#xff1a; <template><el-input-number v-model"value" /> </template><script lang"ts" setup>…...