Linux-网络编程

网络编程概述

本文将介绍网络编程中的一些基础知识,包括TCP和UDP的区别、端口号的作用、字节序的概念,以及通过socket编程实现客户端和服务器之间的通信。我们还会展示一些示例代码,帮助理解这些概念的实际应用。

1. TCP/UDP的区别,端口号的作用

1.1 TCP/UDP的区别

TCP(传输控制协议)UDP(用户数据报协议) 是互联网协议套件中的两个核心传输层协议。它们之间的主要区别如下:

  • 连接方式

    • TCP是面向连接的(如打电话要先拨号建立连接),需要在传输数据之前建立连接。
    • UDP是无连接的,即发送数据之前,不需要建立连接。
  • 可靠性

    • TCP提供可靠的服务,保证数据无差错、不丢失、不重复且按序到达。
    • UDP尽最大努力交付,不保证可靠交付。
  • 数据传输

    • TCP面向字节流,将数据视为一连串无结构的字节流。
    • UDP面向报文,支持面向报文的传输方式。
  • 通信方式

    • 每一条TCP连接只能是点到点的。
    • UDP支持一对一、一对多、多对一和多对多的交互通信。
  • 首部开销

    • TCP首部开销较大,为20字节。
    • UDP首部开销小,只有8字节。
  • 信道类型

    • TCP的逻辑通信信道是全双工的可靠信道。
    • UDP则是不可靠信道。

1.2 端口的作用

IP地址标识网络中的主机,但一台主机可以提供多个网络服务(如Web服务、FTP服务等)。为了区分不同的服务,使用“IP地址+端口号”来标识具体的服务。

  • 端口号 提供了访问通道。服务器通常通过知名端口号来识别。例如,FTP服务器的TCP端口号为21,Telnet服务器的TCP端口号为23,TFTP服务器的UDP端口号为69。

2. 字节序

  • 字节序 指的是多字节数据在内存中的存储顺序。常见的字节序有两种:大端字节序(Big-endian)和小端字节序(Little-endian)。
    • x86系列CPU通常采用小端字节序(Little-endian)。
    • 网络字节序通常采用大端字节序(Big-endian)。

3. Socket编程实现双方消息发送

3.1 Socket服务器实现不断接收客户端信息

通过Socket编程实现一个简单的服务器不断接收客户端信息,并处理数据。以下是一个简单的Socket服务器和客户端示例代码。

server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>int main(int argc, char **argv) {int s_fd;int c_fd;int n_read;char readBuf[128];char *msg = "I got your message";struct sockaddr_in s_addr;struct sockaddr_in c_addr;memset(&s_addr, 0, sizeof(struct sockaddr_in));memset(&c_addr, 0, sizeof(struct sockaddr_in));if (argc != 3) {printf("param isn't right\n");return -1;}// 1. 创建sockets_fd = socket(AF_INET, SOCK_STREAM, 0);if (s_fd == -1) {perror("socket");exit(-1);}s_addr.sin_family = AF_INET;s_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &s_addr.sin_addr);// 2. 绑定地址bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));// 3. 监听端口listen(s_fd, 10);// 4. 接受客户端连接int clen = sizeof(struct sockaddr_in);while (1) {c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &clen);if (c_fd == -1) {perror("accept");continue;}printf("get connect: %s\n", inet_ntoa(c_addr.sin_addr));if (fork() == 0) {// 5. 读取客户端数据n_read = read(c_fd, readBuf, 128);if (n_read == -1) {perror("read");} else {printf("get message: %d, %s\n", n_read, readBuf);}// 6. 发送响应write(c_fd, msg, strlen(msg));break; // 子进程完成一次后退出,父进程继续接收数据}}return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>int main(int argc, char **argv) {int c_fd;int n_read;char readBuf[128];char *msg = "from client msg";struct sockaddr_in c_addr;memset(&c_addr, 0, sizeof(struct sockaddr_in));if (argc != 3) {printf("param isn't right\n");return -1;}// 1. 创建socketc_fd = socket(AF_INET, SOCK_STREAM, 0);if (c_fd == -1) {perror("socket");exit(-1);}c_addr.sin_family = AF_INET;c_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &c_addr.sin_addr);// 2. 连接服务器if (connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in)) == -1) {perror("connect");exit(-1);}// 3. 发送数据int n_write = write(c_fd, msg, strlen(msg));if (n_write == -1) {perror("write");}// 4. 读取响应n_read = read(c_fd, readBuf, 128);if (n_read == -1) {perror("read");} else {printf("get message from server: %d, %s\n", n_read, readBuf);}return 0;
}

4. 一个服务器对应一个客户端作双方交互信息

服务端创建子进程不断接收客户端数据,再创建一个子进程发送数据,做不同的事情;客户端创建子进程发送数据,父进程读取数据;一个进程一个while(1)

server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>int main(int argc, char **argv) {int s_fd;int c_fd;int n_read;char readBuf[128];int mark = 0;char msg[128] = {0};struct sockaddr_in s_addr;struct sockaddr_in c_addr;memset(&s_addr, 0, sizeof(struct sockaddr_in));memset(&c_addr, 0, sizeof(struct sockaddr_in));if (argc != 3) {printf("param isn't right\n");return -1;}// 1. 创建sockets_fd = socket(AF_INET, SOCK_STREAM, 0);if (s_fd == -1) {perror("socket");exit(-1);}s_addr.sin_family = AF_INET;s_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &s_addr.sin_addr);// 2. 绑定地址bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));// 3. 监听端口listen(s_fd, 10);// 4. 接受客户端连接int clen = sizeof(struct sockaddr_in);while (1) {c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &clen);if (c_fd == -1) {perror("accept");continue;}printf("get connect: %s\n", inet_ntoa(c_addr.sin_addr));mark++;if (fork() == 0) {if (fork() == 0) {while (1) {// 6. 发送响应memset(msg, 0, sizeof(msg));sprintf(msg, "welcome %d client", mark);write(c_fd, msg, strlen(msg));sleep(3);}}// 5. 读取客户端数据while (1) {memset(readBuf, 0, sizeof(readBuf));n_read = read(c_fd, readBuf, 128);if (n_read == -1) {perror("read");} else {printf("\nget: %s\n", readBuf);}}break;}}return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>int main(int argc, char **argv) {int c_fd;int n_read;char readBuf[128];char msg[128] = {0};struct sockaddr_in c_addr;memset(&c_addr, 0, sizeof(struct sockaddr_in));if (argc != 3) {printf("param isn't right\n");return -1;}// 1. 创建socketc_fd = socket(AF_INET, SOCK_STREAM, 0);if (c_fd == -1) {perror("socket");exit(-1);}c_addr.sin_family = AF_INET;c_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &c_addr.sin_addr);// 2. 连接服务器if (connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in)) == -1) {perror("connect");exit(-1);}while (1) {if (fork() == 0) {while (1) {// 3. 发送数据memset(msg, 0, sizeof(msg));printf("input: ");gets(msg);write(c_fd, msg, strlen(msg));}}while (1) {// 4. 读取响应memset(readBuf, 0, sizeof(readBuf));n_read = read(c_fd, readBuf, 128);if (n_read == -1) {perror("read");} else {printf("\nget: %s\n", readBuf);}}}return 0;
}

5. 服务器与多个客户端聊天,服务器自动回复

server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>int main(int argc, char **argv) {int s_fd;int c_fd;int n_read;int mark = 0;char buf[128] = {0};char msg[128] = {0};struct sockaddr_in s_addr;struct sockaddr_in c_addr;memset(&s_addr, 0, sizeof(struct sockaddr_in));memset(&c_addr, 0, sizeof(struct sockaddr_in));if (argc != 3) {printf("params no ok\n");exit(-1);}// 1. 创建sockets_fd = socket(AF_INET, SOCK_STREAM, 0);if (s_fd == -1) {perror("socket");exit(-1);}// 2. 绑定地址s_addr.sin_family = AF_INET;s_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &s_addr.sin_addr);bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));// 3. 监听端口listen(s_fd, 10);int len = sizeof(struct sockaddr_in);while (1) {// 4. 接受客户端连接c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &len);if (c_fd == -1) {perror("accept");continue;}mark++;printf("get connect: %s\n", inet_ntoa(c_addr.sin_addr));if (fork() == 0) {if (fork() == 0) {// 5. 发送自动回复消息while (1) {memset(msg, 0, sizeof(msg));sprintf(msg, "welcome No %d client", mark);write(c_fd, msg, strlen(msg));sleep(2);}}// 6. 读取客户端消息while (1) {memset(buf, 0, sizeof(buf));n_read = read(c_fd, buf, sizeof(buf));if (n_read == -1) {perror("read");} else {printf("read client: %s\n", buf);}}}}close(s_fd);return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>int main(int argc, char **argv) {int c_fd;int n_read;char buf[128] = {0};char msg[128] = {0};struct sockaddr_in c_addr;memset(&c_addr, 0, sizeof(struct sockaddr_in));if (argc != 3) {printf("params is no ok\n");exit(-1);}// 1. 创建socketc_fd = socket(AF_INET, SOCK_STREAM, 0);if (c_fd == -1) {perror("socket");exit(-1);}// 2. 绑定地址c_addr.sin_family = AF_INET;c_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &c_addr.sin_addr);// 3. 连接服务器if (connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in)) == -1) {perror("connect");exit(-1);}while (1) {if (fork() == 0) {while (1) {// 4. 发送消息memset(msg, 0, sizeof(msg));printf("input: ");gets(msg);write(c_fd, msg, strlen(msg));}}while (1) {// 5. 接收消息memset(buf, 0, sizeof(buf));n_read = read(c_fd, buf, sizeof(buf));if (n_read == -1) {perror("read");} else {printf("read server: %s\n", buf);}}}close(c_fd);return 0;
}

6. FTP云盘

FTP云盘功能实现,包含以下功能:

  • lls: 列出本地的文件
  • lcd: 进入本地的文件路径
  • cd: 进入服务端的路径
  • ls: 列出服务端的文件
  • quit: 退出客户端
  • get: 获取服务端的文件
  • put: 上传客户端的文件

server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"int get_cmd_type(char *cmd) {if (strcmp("ls", cmd) == 0) return LS;if (strcmp("pwd", cmd) == 0) return PWD;if (strcmp("quit", cmd) == 0) return QUIT;if (strstr(cmd, "cd")) return CD;if (strstr(cmd, "get")) return GET;if (strstr(cmd, "put")) return PUT;return -1;
}char* getDir(char *cmd) {char *p = NULL;p = strtok(cmd, " ");p = strtok(NULL, " ");return p;
}void cmdHandler(struct MSG msg, int c_fd) {int ret;int fd;int p_fd;FILE *fp;char *filename = NULL;char *file = NULL;char *filename2 = NULL;char dataBuf[1024] = {0};printf("%s\n", msg.cmd);ret = get_cmd_type(msg.cmd);printf("ret=%d\n", ret);switch (ret) {case LS:case PWD:fp = popen(msg.cmd, "r");fread(msg.cmd, sizeof(msg.cmd), 1, fp);write(c_fd, &msg, sizeof(msg));break;case CD:filename = getDir(msg.cmd);printf("filename: %s\n", filename);chdir(filename);break;case GET:file = getDir(msg.cmd);if (access(file, F_OK) == -1) {strcpy(msg.cmd, "NO this file");write(c_fd, &msg, sizeof(msg));} else {msg.type = 8;fd = open(file, O_RDWR);read(fd, dataBuf, sizeof(dataBuf));close(fd);strcpy(msg.cmd, dataBuf);write(c_fd, &msg, sizeof(msg));printf("success\n");}break;case PUT:filename2 = getDir(msg.cmd);printf("filename: %s\n", filename2);p_fd = open(filename2, O_RDWR | O_CREAT, 0666);write(p_fd, msg.dataBuf, strlen(msg.dataBuf));printf("write success\n");close(p_fd);break;case QUIT:printf("client out\n");exit(-1);break;}
}int main(int argc, char **argv) {int s_fd;int c_fd;int n_read;struct sockaddr_in s_addr;struct sockaddr_in c_addr;struct MSG msg;memset(&s_addr, 0, sizeof(struct sockaddr_in));memset(&c_addr, 0, sizeof(struct sockaddr_in));if (argc != 3) {printf("params is no ok\n");exit(-1);}// 1. 创建sockets_fd = socket(AF_INET, SOCK_STREAM, 0);if (s_fd == -1) {perror("socket");exit(-1);}// 2. 绑定地址s_addr.sin_family = AF_INET;s_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &s_addr.sin_addr);bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));// 3. 监听端口listen(s_fd, 10);int len = sizeof(struct sockaddr_in);while (1) {// 4. 接受客户端连接c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &len);if (c_fd == -1) {perror("accept");continue;}printf("get connect: %s\n", inet_ntoa(c_addr.sin_addr));if (fork() == 0) {while (1) {memset(&msg.cmd, 0, sizeof(msg));n_read = read(c_fd, &msg, sizeof(msg));if (n_read == 0) {printf("client out");break;} else if (n_read > 0) {cmdHandler(msg, c_fd);}}}}close(s_fd);close(c_fd);return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"int get_cmd_type(char *cmd) {if (strcmp(cmd, "ls") == 0) return LS;if (strcmp(cmd, "pwd") == 0) return PWD;if (strcmp(cmd, "quit") == 0) return QUIT;if (strstr(cmd, "lcd")) return LCD;if (strstr(cmd, "cd")) return CD;if (strstr(cmd, "lls")) return LLS;if (strstr(cmd, "get")) return GET;if (strstr(cmd, "put")) return PUT;return -1;
}char* getDir(char *cmd) {char *p = NULL;p = strtok(cmd, " ");p = strtok(NULL, " ");return p;
}int cmd_handler(struct MSG msg, int c_fd) {int ret;int fd;char *filename = NULL;char *dir = NULL;char buf[32] = {0};ret = get_cmd_type(msg.cmd);switch (ret) {case LS:case PWD:case CD:case GET:write(c_fd, &msg, sizeof(msg));break;case LLS:system("ls");break;case LCD:filename = getDir(msg.cmd);printf("filename: %s\n", filename);chdir(filename);break;case PUT:strcpy(buf, msg.cmd);dir = getDir(buf);printf("dir: %s\n", dir);if (access(dir, F_OK) == -1) {printf("%s no exsit\n", dir);} else {fd = open(dir, O_RDWR);read(fd, msg.dataBuf, strlen(msg.dataBuf));close(fd);write(c_fd, &msg, sizeof(msg));printf("ok\n");}break;case QUIT:write(c_fd, &msg, sizeof(msg));close(c_fd);exit(-1);break;}return ret;
}void cmd_serverMsg_handler(struct MSG msg, int c_fd) {int n_read;int fd;char *file = NULL;struct MSG getmsg;n_read = read(c_fd, &getmsg, sizeof(getmsg));if (n_read == 0) {printf("server quit\n");}if (getmsg.type == 8) {file = getDir(msg.cmd);fd = open(file, O_RDWR | O_CREAT, 0600);printf("open success\n");write(fd, getmsg.cmd, strlen(getmsg.cmd));} else {printf("-------------------------------------\n");printf("%s\n", getmsg.cmd);printf("-------------------------------------\n");}
}int main(int argc, char **argv) {int c_fd;int ret;struct sockaddr_in c_addr;struct MSG msg;memset(&c_addr, 0, sizeof(struct sockaddr_in));if (argc != 3) {printf("params is no good\n");exit(-1);}// 1. 创建socketc_fd = socket(AF_INET, SOCK_STREAM, 0);if (c_fd == -1) {perror("socket");exit(-1);}// 2. 连接服务器c_addr.sin_family = AF_INET;c_addr.sin_port = htons(atoi(argv[2]));inet_aton(argv[1], &c_addr.sin_addr);if (connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in)) == -1) {perror("connect");exit(-1);}printf("connect....\n");// 3. 处理命令while (1) {memset(msg.cmd, 0, sizeof(msg));gets(msg.cmd);ret = cmd_handler(msg, c_fd);if (ret == CD || ret == LLS || ret == LCD || ret == QUIT || ret == PUT) {continue;}if (ret == -1) {printf("this is command no exist\n");continue;}cmd_serverMsg_handler(msg, c_fd);}close(c_fd);return 0;
}

config.h

#define LS   0
#define PWD  1
#define CD   2
#define GET  3
#define PUT  4
#define LLS  5
#define LCD  6
#define QUIT 7struct MSG {int type;char cmd[1024];char dataBuf[1024];
};

通过上述代码示例,展示了如何通过socket编程实现客户端和服务器之间的通信,包括简单的消息传递、多客户端处理以及文件传输等功能。希望这些示例代码能帮助理解和应用网络编程中的一些基本概念和技术。

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

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

相关文章

VSCode + GDB + J-Link 单片机程序调试实践

VSCode GDB J-Link 单片机程序调试实践 本文介绍如何创建VSCode的调试配置&#xff0c;如何控制调试过程&#xff0c;如何查看修改各种变量。 安装调试插件 在 VSCode 扩展窗口搜索安装 Cortex-Debug插件 创建调试配置 在 Run and Debug 窗口点击 create a launch.json …

【单片机毕业设计11-基于stm32c8t6的智能水质检测】

【单片机毕业设计11-基于stm32c8t6的智能水质检测】 前言一、功能介绍二、硬件部分三、软件部分总结 前言 &#x1f525;这里是小殷学长&#xff0c;单片机毕业设计篇11基于stm32的智能水质检测系统 &#x1f9ff;创作不易&#xff0c;拒绝白嫖可私 一、功能介绍 -------------…

Java----面向对象----总复习

面向对象 面向对象的程序设计思想(Object Oriented Programming),简称OOP.是一种设计者思想.关注的焦点是类,参照现实中的事务,将事务的属性特征,行为抽象出来,用类来表示.代码结构:以类为组织单位,每种事务都有自己的属性和行为,功能, 思想:从宏观上 帮助我们把握,整体分析整…

Bazel plugin for Visual Studio Code

语法突出显示 Bazel Build Targets 树显示工作区中的构建包/目标BUILD 文件中的 CodeLens 链接可通过单击目标直接启动构建或测试Buildifier 集成以检查和格式化您的 Bazel 文件&#xff08;需要安装 Buildifier&#xff09;tasks.json 的 Bazel Task 定义在构建期间调试 .bzl…

C++:静态断言内存对齐

静态断言 C中的断言assert (1)直接参考&#xff1a;https://www.cnblogs.com/lvchaoshun/p/7816288.html (2)C的assert是运行时检测发现错误&#xff0c;而不是编译时 (3)C在编译时错误用#error来输出C静态断言 (1)C引入static_assert(表达式, “提示字符串”)来实现编译时的静…

window搭建git环境

1.下载安装window下git专用软件scm 从Git for Windows 官网网站下载&#xff0c;并且一路安装即可 安装成功后通过桌面快捷图标Git Bash点击打开 安装后软件应该会自动帮助配置环境变量&#xff0c;如果没有需要自己配置使用 2.git环境配置 2.1设置姓名和邮箱(github上你注…

封装了一个iOS滚动厨窗效果

效果图 背景 我们要实现如图的厨窗效果&#xff0c;不能通过在tableView底部添加一个背景图片的方式&#xff0c;因为这需要修改整个tableView的背景色为透明&#xff0c;影响到的范围太大&#xff0c;只能将这个效果局限在这个cell 中&#xff0c;然后通过监听tableView的滚动…

追觅科技25届校招校招24年社招科技北森题库商业推理综合测评答题攻略、通关技巧

一、追觅科技这家公司怎么样&#xff1f; 追觅科技是一家在智能清洁家电领域表现出色的企业。 二、追觅科技待遇怎么样 追觅科技的待遇在业内具有竞争力&#xff0c;具体信息如下&#xff1a; 1. **薪酬结构**&#xff1a;根据对外经济贸易大学招生就业处发布的2023届校园招…

虹科技术丨跨越距离障碍:PCAN系列网关在远程CAN网络通信的应用潜力

来源&#xff1a;虹科技术丨跨越距离障碍&#xff1a;PCAN系列网关在远程CAN网络通信的应用潜力 原文链接&#xff1a;虹科技术 | 跨越距离障碍&#xff1a;PCAN系列网关在远程CAN网络通信的应用潜力 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; #PCAN #网关 #CA…

Flask之电子邮件

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、使用Flask-Mail发送电子邮件 1.1、配置Flask-Mail 1.2、构建邮件数据 1.3、发送邮件 二、使用事务邮件服务SendGrid 2.1、注册SendGr…

最新源支付系统源码 V7版全开源 免授权 附搭建教程

最新源支付系统源码_V7版全开源_免授权_附详细搭建教程_站长亲测 YPay是专为个人站长打造的聚合免签系统&#xff0c;拥有卓越的性能和丰富的功能。它采用全新轻量化的界面UI&#xff0c;让您能更方便快捷地解决知识付费和运营赞助的难题。同时&#xff0c;它基于高性能的thin…

TypeScript学习笔记(全)

文章目录 TypeScript入门2.编译并运行TS代码2.1.简化运行ts步骤 3.TS中的常用类型3.1.TS中的类型注解3.2.TS中的原始类型3.3.TS中的数组类型3.4.TS中的联合类型3.5.类型别名3.6.函数类型3.6.1.单独执行参数、返回值类型3.6.2.同时指定参数&#xff0c;返回值类型3.6.3.函数的vo…

广东省钟表行业协会第十二届会员大会暨2024年钟表行业发展交流会

6月25日广东省钟表行业协会第十二届会员大会暨2024年钟表行业发展交流会在广州万富希尔顿酒店隆重召开。大会选举沙胜昔为广东省钟表行业协会第十二届理事会会长。 领导发言 新任会长 沙胜昔 首席荣誉会长 吴伟阳 新老会长交接仪式 本次大会&#xff0c;全国钟表大伽齐参与…

前端Web开发HTML5+CSS3+移动web视频教程 Day3 CSS 第1天

P29 - P43 从此开始进入 CSS 的学习。前面都是 HTML 的学习。 CSS 的作用&#xff1a;美化。 HTML 只是规定了网页内容有哪些&#xff0c;在网页中显示的位置默认是从上到下显示&#xff0c;还带有默认效果&#xff0c;比如超链接有颜色有下划线&#xff0c;无序列表有小圆点…

CSS Flex弹性布局

一、传统布局与flex布局 1、传统布局 2、flex布局 二、flex布局原理 1、布局原理 2、flex布局体验 三、flex布局父项常见属性 1、常见的父项属性 2、flex-direction设置主轴的方向 3、justify-content 设置主轴上的子元素排列方式 4、flex-wrap 设置子元素是否换行 …

二叉树从根节点出发的所有路径

二叉树从根节点出发的所有路径 看上图中 二叉树结构 从根节点出发的所有路径 如下 6->4->2->1 6->4->2->3 6->4->5 6->8->7 6->8->9 逻辑思路&#xff1a; 按照先序遍历 加 回溯法 实现 代码如下 // 调用此方法&#xff0c;将根节点传递…

上位机图像处理和嵌入式模块部署(mcu 项目1:上位机编写)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面&#xff0c;我们说过要做一个报警器。如果只是简单做一个报警器呢&#xff0c;这个基本上没有什么难度。这里&#xff0c;我们就适当提高一下…

Navicat上新啦

前言 Navicat&#xff0c;在数据库界&#xff0c;几乎是一个神奇的存在&#xff0c;似乎统治了数据库开发工具的“一片天”。且看下图&#xff1a; 红的蓝的绿的橙的…&#xff0c;可以说&#xff0c;留给它的color不多了。 那么商业BI到服务监控、从云托管到云协作&#xff…

短剧App开发的全攻略

短剧App开发的全攻略可以概括为以下几个关键步骤&#xff1a; 1、市场调研与需求分析 进行市场调研&#xff0c;研究目标用户群体&#xff0c;了解他们的需求和偏好。 观察竞争对手的App&#xff0c;分析他们的优点和缺点&#xff0c;以此为基础来制定自己的开发计划。 确定App…

Zookeeper节点ACL权限设置—digest模式

ACL全称为Access Control List&#xff08;访问控制列表&#xff09;&#xff0c;用于控制资源的访问权限。ZooKeeper使用ACL来控制对其znode&#xff08;ZooKeeper数据树的数据节点&#xff09;的访问。 zk利用ACL策略控制节点的访问权限: CREATE c 可以创建子节点 DELETE …