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

lv7 嵌入式开发-网络编程开发 07 TCP服务器实现

目录

1 函数介绍

1.1 socket函数 与 通信域

1.2 bind函数 与 通信结构体

1.3 listen函数 与 accept函数

2 TCP服务端代码实现

 3 TCP客户端代码实现

4 代码优化

5 练习


1 函数介绍

其中read、write、close在IO中已经介绍过,只需了解socket、bind、listen、accept等

1.1 socket函数 与 通信域

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

参数:

  • domain:指定套接字的协议域(protocol family),可以是 AF_INET(IPv4)或 AF_INET6(IPv6)等。
  • type:指定套接字的类型,可以是 SOCK_STREAM(流套接字,用于可靠的、面向连接的通信)或 SOCK_DGRAM(数据报套接字,用于无连接的通信)等。
  • protocol:指定使用的协议,可以是 IPPROTO_TCP(TCP)或 IPPROTO_UDP(UDP)等。所以无需要指定协议,设为0即可

返回值:

  • 成功创建套接字时,返回一个非负整数,代表新创建的套接字描述符。
  • 创建套接字失败时,返回 -1,并设置 errno 来表示具体的错误原因。

 示例:

#include <sys/types.h>
#include <sys/socket.h>int main() {int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  //最后一个参数也可以是0if (sockfd == -1) {// 处理创建套接字失败的情况return -1;}// 套接字创建成功,可以进行后续操作return 0;
}

1.2 bind函数 与 通信结构体

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数解释:

  • sockfd:要进行绑定的套接字描述符。
  • addr:指向sockaddr结构体的指针,其中包含了要绑定的地址信息。
  • addrlenaddr指向的结构体的大小。

返回值:

  • 成功时,返回0。
  • 失败时,返回-1,并且在错误码中设置相应的错误标志,可以通过errno全局变量获取具体错误信息。

ipv4结构体 

struct sockaddr_in {sa_family_t    sin_family; /* 地址族: AF_INET */in_port_t      sin_port;   /* 网络字节序的端口号 */struct in_addr sin_addr;   /*IP地址结构体 */
};/* IP地址结构体 */
struct in_addr {uint32_t       s_addr;     /* 网络字节序的IP地址 */
};/*通用地址族结构体*/
struct sockaddr {sa_family_t sa_family;char sa_data[14];
}

注意事项:

  • 调用bind()函数之前,需要先创建一个套接字,并确保该套接字是未绑定的。
  • bind()函数通常在服务器端使用,用于将服务器的套接字与指定的本地地址绑定,从而监听并接收该地址发来的连接请求。
  • 在调用bind()函数时,要根据实际情况提供正确的地址信息,如IP地址和端口号等。
  • 在IPv4中,地址信息存储在sockaddr_in结构体中;而在IPv6中,地址信息存储在sockaddr_in6结构体中。

示例:强制转换

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>int main() {int sockfd;struct sockaddr_in server_addr;// 创建套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);// 设置服务器地址信息server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8080);server_addr.sin_addr.s_addr = INADDR_ANY;// 绑定套接字和地址if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("bind");return 1;}// 其他操作...return 0;
}

1.3 listen函数 与 accept函数

/*监听套接字*/
int listen(int sockfd, int backlog);

参数:

  • sockfd:要监听的套接字描述符。
  • backlog:定义允许排队等待的连接请求的最大数量。

返回值:

  • 成功调用 listen() 函数时,返回 0 表示成功。
  • 调用 listen() 函数失败时,返回 -1 并设置 errno 来表示具体的错误原因。

函数功能: listen() 函数被用于 TCP 服务器端,用于将指定的套接字标记为被动套接字(passive socket),开始监听传入的连接请求。在调用 listen() 之前,服务器需要使用 socket() 函数创建一个套接字,并使用 bind() 函数将套接字与特定的地址和端口绑定。

一旦套接字被标记为监听状态,它就可以开始接受传入的连接请求。这些连接请求会被放置在一个连接请求队列中,等待服务器进程使用 accept() 函数来接受这些请求并建立连接。

注意事项:

  • backlog 参数指定了连接请求队列的最大长度。如果队列已满,则新的连接请求将被拒绝。实际允许的队列长度可能会受到系统限制。
  • 在调用 listen() 之后,通常需要调用 accept() 函数来接受连接请求并建立连接。

示例:

#include <sys/types.h>
#include <sys/socket.h>int main() {int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sockfd == -1) {// 处理创建套接字失败的情况return -1;}// 套接字创建成功,可以进行后续操作if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {// 处理绑定地址和端口失败的情况return -1;}if (listen(sockfd, 10) == -1) {// 处理监听套接字失败的情况return -1;}// 套接字处于监听状态,可以接受连接请求并建立连接return 0;
}

/*处理客户端发起的连接,生成新的套接字*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-sockfd: 函数socket生成的套接字
-addr:客户端的地址族信息
-addrlen:地址族结构体的长度

参数:

  • sockfd:监听套接字描述符,即之前调用 listen() 函数返回的套接字描述符。
  • addr:指向用于存储客户端地址信息的结构体 sockaddr 的指针,可以为 NULL
  • addrlen:指向存储客户端地址长度的变量的指针,如果 addr 不为 NULL,则需要将 addrlen 设置为 sizeof(struct sockaddr)

返回值:

  • 成功调用 accept() 函数时,返回一个新的套接字描述符,用于处理与客户端的连接。
  • 调用 accept() 函数失败时,返回 -1 并设置 errno 来表示具体的错误原因。

函数功能: accept() 函数用于监听套接字上接受传入的连接请求,并创建一个新的套接字来处理与客户端的连接。该新的套接字用于与客户端进行通信。在调用 accept() 函数之前,需要先使用 socket()bind()listen() 函数来准备监听套接字。

当有一个连接请求到达监听套接字时,accept() 函数会从连接请求队列中取出一个请求,创建一个新的套接字来处理该连接,并返回新创建的套接字描述符。可以通过新创建的套接字描述符进行与客户端的通信。

如果传入的 addr 不为 NULL,则 accept() 函数会将客户端的地址信息存储在 addr 指向的结构体中。同时,addrlen 也需要传入一个指向存储客户端地址长度的变量的指针。

注意事项:

  • accept() 函数是一个阻塞调用,当没有连接请求时,它会一直等待,直到有连接请求到达或出现错误才返回。
  • 通常在多线程或多进程环境中使用 accept() 函数来实现并发处理多个连接请求的功能。

示例: 

#include <sys/types.h>
#include <sys/socket.h>int main() {int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sockfd == -1) {// 处理创建套接字失败的情况return -1;}// 套接字创建成功,可以进行后续操作if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {// 处理绑定地址和端口失败的情况return -1;}if (listen(sockfd, 10) == -1) {// 处理监听套接字失败的情况return -1;}// 套接字处于监听状态,可以接受连接请求并建立连接struct sockaddr_in client_addr;socklen_t client_addrlen = sizeof(client_addr);int client_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_addrlen);if (client_sockfd == -1) {// 处理接受连接请求失败的情况return -1;}// 成功接受连接请求,可以使用 client_sockfd 进行与客户端的通信return 0;
}

2 TCP服务端代码实现

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>#define PORT 5001
#define BACKLOG 5int main(int argc, char *argv[])
{int fd, newfd;char buf[BUFSIZ] = {}; //BUFSIZ 8142struct sockaddr_in addr;/*创建套接字*/fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){perror("socket");exit(0);}addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = 0;/*绑定通信结构体*/if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){perror("bind");exit(0);}/*设置套接字为监听模式*/if(listen(fd, BACKLOG) == -1){perror("listen");exit(0);}/*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/newfd = accept(fd, NULL, NULL);if(newfd < 0){perror("accept");exit(0);}printf("BUFSIZ = %d\n", BUFSIZ);read(newfd, buf, BUFSIZ);printf("buf = %s\n", buf);close(fd);return 0;
}

 3 TCP客户端代码实现

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>#define PORT 5001
#define BACKLOG 5
#define STR "Hello World!"int main(int argc, char *argv[])
{int fd;struct sockaddr_in addr;/*创建套接字*/fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){perror("socket");exit(0);}addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = inet_addr("127.0.0.1");/*向服务端发起连接请求*/if(connect(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){perror("connect");exit(0);}write(fd, STR, sizeof(STR) );printf("STR = %s\n", STR);close(fd);return 0;
}

4 代码优化

服务端

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>#define BACKLOG 5int main(int argc, char *argv[])
{int fd, newfd, ret;char buf[BUFSIZ] = {}; //BUFSIZ 8142struct sockaddr_in addr;if(argc < 3){fprintf(stderr, "%s<addr><port>\n", argv[0]);exit(0);}/*创建套接字*/fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){perror("socket");exit(0);}addr.sin_family = AF_INET;addr.sin_port = htons( atoi(argv[2]) );if ( inet_aton(argv[1], &addr.sin_addr) == 0) {fprintf(stderr, "Invalid address\n");exit(EXIT_FAILURE);}/*绑定通信结构体*/if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){perror("bind");exit(0);}/*设置套接字为监听模式*/if(listen(fd, BACKLOG) == -1){perror("listen");exit(0);}/*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/newfd = accept(fd, NULL, NULL);if(newfd < 0){perror("accept");exit(0);}while(1){memset(buf, 0, BUFSIZ);ret = read(newfd, buf, BUFSIZ);if(ret < 0){perror("read");exit(0);}else if(ret == 0)break;elseprintf("buf = %s\n", buf);}close(newfd);close(fd);return 0;
}

客户端

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>#define BACKLOG 5int main(int argc, char *argv[])
{int fd;struct sockaddr_in addr;char buf[BUFSIZ] = {};if(argc < 3){fprintf(stderr, "%s<addr><port>\n", argv[0]);exit(0);}/*创建套接字*/fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){perror("socket");exit(0);}addr.sin_family = AF_INET;addr.sin_port = htons( atoi(argv[2]) );if ( inet_aton(argv[1], &addr.sin_addr) == 0) {fprintf(stderr, "Invalid address\n");exit(EXIT_FAILURE);}/*向服务端发起连接请求*/if(connect(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){perror("connect");exit(0);}while(1){printf("Input->");fgets(buf, BUFSIZ, stdin);write(fd, buf, strlen(buf) );}close(fd);return 0;
}

5 练习

实现TCP通信代码,并使用Makefile进行编译。提交代码和完成通信的截图

client

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>#define CLIENT_MAX_NUM 5int main(int argc, char * argv[])
{int clientfd;struct sockaddr_in server_addr;char buf[BUFSIZ];int ret;if( argc < 3){printf("%s <ip> <port>\n",argv[0]);return 0;}clientfd = socket(AF_INET, SOCK_STREAM,0);if(clientfd == -1){perror("socket");return 0;}server_addr.sin_family = AF_INET;server_addr.sin_port = htons( atoi(argv[2]) ) ;if( inet_aton(argv[1], &server_addr.sin_addr) == 0){printf("Invalid address:%s\n",argv[1]);return 0;}if(connect(clientfd, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1){perror("connect");return 0;}while(1){printf(">");fgets(buf, BUFSIZ, stdin);write(clientfd, buf, strlen(buf));}close(clientfd);return 0;
}

server

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>#define CLIENT_MAX_NUM 5int main(int argc, char * argv[])
{int sockfd, clientfd;struct sockaddr_in server_addr;char buf[BUFSIZ];int ret;if( argc < 3){printf("%s <ip> <port>\n",argv[0]);return 0;}sockfd = socket(AF_INET, SOCK_STREAM,0);if(sockfd == -1){perror("socket");return 0;}server_addr.sin_family = AF_INET;server_addr.sin_port = htons( atoi(argv[2]) ) ;if( inet_aton(argv[1], &server_addr.sin_addr) == 0){printf("Invalid address:%s\n",argv[1]);return 0;}if(bind(sockfd, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1){perror("bind");return 0;}if(listen(sockfd, CLIENT_MAX_NUM) == -1){perror("listen");return 0;}clientfd = accept(sockfd, NULL, NULL); if( clientfd == -1){perror("accept");return 0;}while(1){memset(buf, 0, BUFSIZ);ret = read(clientfd, buf, BUFSIZ);if(ret < 0){perror("read");return 0;}else if( ret == 0 ){break;}else{printf("buf = %s\n", buf);}	}close(clientfd);close(sockfd);return 0;
}

makefile

CC=gcc
CFLAGS=-Wall
all:tcp_client tcp_serverclean:rm tcp_server tcp_client

相关文章:

lv7 嵌入式开发-网络编程开发 07 TCP服务器实现

目录 1 函数介绍 1.1 socket函数 与 通信域 1.2 bind函数 与 通信结构体 1.3 listen函数 与 accept函数 2 TCP服务端代码实现 3 TCP客户端代码实现 4 代码优化 5 练习 1 函数介绍 其中read、write、close在IO中已经介绍过&#xff0c;只需了解socket、bind、listen、acc…...

mysql技术文档--阿里巴巴java准则《Mysql数据库建表规约》--结合阿丹理解尝试解读--国庆开卷

阿丹&#xff1a; 国庆快乐呀大家&#xff01; 在项目开始前一个好的设计、一个健康的表关系&#xff0c;不仅会让开发变的有趣舒服&#xff0c;也会在后期的维护和升级迭代中让系统不断的成长。那么今天就认识和解读一下阿里的准则&#xff01;&#xff01; 建表规约 表达是…...

Qt+openCV学习笔记(十六)Qt6.6.0rc+openCV4.8.1+emsdk3.1.37编译静态库

前言&#xff1a; 有段时间没来写文章了&#xff0c;趁编译库的空闲&#xff0c;再写一篇记录文档 WebAssembly的发展逐渐成熟&#xff0c;即便不了解相关技术&#xff0c;web前端也在不经意中使用了相关技术的库&#xff0c;本篇文档记录下如何编译WebAssembly版本的openCV&…...

JUC第十四讲:JUC锁: ReentrantReadWriteLock详解

JUC第十四讲&#xff1a;JUC锁: ReentrantReadWriteLock详解 本文是JUC第十四讲&#xff1a;JUC锁 - ReentrantReadWriteLock详解。ReentrantReadWriteLock表示可重入读写锁&#xff0c;ReentrantReadWriteLock中包含了两种锁&#xff0c;读锁ReadLock和写锁WriteLock&#xff…...

在vue3中使用vite-svg-loader插件

vite-svg-loader插件可以让我们像使用vue组件那样使用svg图&#xff0c;使用起来超级方便。 安装 npm install vite-svg-loader --save-dev使用 import svgLoader from vite-svg-loaderexport default defineConfig({plugins: [vue(), svgLoader()] })组件里使用 在路径后加…...

国庆10.4

QT实现TCP服务器客户端 服务器 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器头文件 #include <QTcpSocket> //客户端头文件 #include <QList> //链表容器 #include <QMe…...

2023/8/12 下午8:41:46 树状控件guilite

2023/8/12 下午8:41:46 树状控件guilite 2023/8/12 下午8:42:08 树状控件(Tree View)是一种常见的图形用户界面(GUI)元素,它通常用于显示层次结构数据或文件系统的目录结构。Guilite 是一个轻量级的跨平台 GUI 库,支持多种控件,包括树状控件。 在 Guilite 中使用树状…...

BL808学习日志-2-LVGL for M0 and D0

一、lvgl测试环境 对拿到的M1S_DOCK开发板进行开发板测试&#xff0c;博流的官方SDK是支持M0和D0两个内核都进行测试的&#xff1b;但是目前只实现了M0的LVGLBenchmark&#xff0c;测试D0内核中发现很多莫名其妙的问题。一会详细记录。 使用的是开发板自带的SPI显示屏&#xff…...

treectrl类封装 2023/8/13 下午4:07:35

2023/8/13 下午4:07:35 treectrl类封装 2023/8/13 下午4:07:53 TreeCtrl 类是一个常用的图形用户界面控件,用于实现树形结构的展示和交互。以下是一个简单的 TreeCtrl 类的封装示例: python import wxclass MyTreeCtrl(wx.TreeCtrl):def __init__(self, parent):super()…...

Android学习之路(20) 进程间通信

IPC IPC为 (Inter-Process Communication) 缩写&#xff0c;称为进程间通信或跨进程通信&#xff0c;指两个进程间进行数据交换的过程。安卓中主要采用 Binder 进行进程间通信&#xff0c;当然也支持其他 IPC 方式&#xff0c;如&#xff1a;管道&#xff0c;Socket&#xff0…...

机器学习——KNN算法流程详解(以iris为例)

、 目 录 前情说明 问题陈述 数据说明 KNN算法流程概述 代码实现 运行结果 基于可视化的改进 可视化代码 全部数据可视化总览 分类投票结果 改进后最终代码 前情说明 本书基于《特征工程入门与入门与实践》庄家盛 译版P53页K最近邻&#xff08;KNN&#xff09;算…...

国庆假期day5

作业&#xff1a;请写出七层模型及每一层的功能&#xff0c;请绘制三次握手四次挥手的流程图 1.OSI七层模型&#xff1a; 应用层--------提供函 表示层--------表密缩 会话层--------会话 传输层--------进程的接收和发送 网络层--------寻主机 数据链路层----相邻节点的可靠传…...

ES6中的let、const

let ES6中新增了let命令&#xff0c;用来声明变量&#xff0c;和var类似但是也有一定的区别 1. 块级作用域 只能在当前作用域内使用&#xff0c;各个作用域不能互相使用&#xff0c;否则会报错。 {let a 1;var b 1; } console.log(a); // 会报错 console.log(b); // 1为什…...

Python 列表操作指南3

示例&#xff0c;将新列表中的所有值设置为 ‘hello’&#xff1a; newlist [hello for x in fruits]表达式还可以包含条件&#xff0c;不像筛选器那样&#xff0c;而是作为操纵结果的一种方式&#xff1a; 示例&#xff0c;返回 “orange” 而不是 “banana”&#xff1a; …...

三个要点,掌握Spring Boot单元测试

单元测试是软件开发中不可或缺的重要环节&#xff0c;它用于验证软件中最小可测试单元的准确性。结合运用Spring Boot、JUnit、Mockito和分层架构&#xff0c;开发人员可以更便捷地编写可靠、可测试且高质量的单元测试代码&#xff0c;确保软件的正确性和质量。 一、介绍 本文…...

【nginx】Nginx配置:

文章目录 一、什么是Nginx&#xff1a;二、为什么使用Nginx&#xff1a;三、如何处理请求&#xff1a;四、什么是正向代理和反向代理&#xff1a;五、nginx 启动和关闭&#xff1a;六、目录结构&#xff1a;七、配置文件nginx.conf&#xff1a;八、location&#xff1a;九、单页…...

CSS3与HTML5

box-sizing content-box&#xff1a;默认&#xff0c;宽高包不含边框和内边距 border-box&#xff1a;也叫怪异盒子&#xff0c;宽高包含边框和内边距 动画&#xff1a;移动translate&#xff0c;旋转、transform等等 走马灯&#xff1a;利用动画实现animation&#xff1a;from…...

redis的简单使用

文章目录 环境安装与配置redis发布-订阅相关命令redis发布-订阅的客户端编程redis的订阅发布的例子 环境安装与配置 sudo apt-get install redis-server # ubuntu命令安装redis服务ubuntu通过上面命令安装完redis&#xff0c;会自动启动redis服务&#xff0c;通过ps命令确认&a…...

Windows下启动freeRDP并自适应远端桌面大小

几个二进制文件 xfreerdp # Linux下的&#xff0c;an X11 Remote Desktop Protocol (RDP) client which is part of the FreeRDP project wfreerdp.exe # Windows下的&#xff0c;freerdp2.0 主程序&#xff0c;freerdp3.0将废弃 sdl-freerdp.exe # Windows下的&…...

ES6中的数值扩展

1. 二进制和八进制的表示法 二进制和八进制的前缀分别为0b(或0B)和0o(或0O)表示 在ES5的严格模式下&#xff0c;八进制不再允许使用前缀0表示 如果要将0b和0x前缀的字符串数值转为十进制&#xff0c;要使用Number方法 Number(0b111); // 7 Number(0o10); // 82. Number.isF…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...