Linux C语言 31-网络编程之TCP例程

Linux C语言 31-网络编程之TCP例程

本节关键字:C语言 网络编程 套接字操作 TCP协议 服务端 客户端 非阻塞
相关C库函数:setsockopt, socket, bind, listen, accept, recv, send, close, select, connect

相关接口介绍

Linux C语言 30-套接字操作

例程执行任务说明

本例程中服务端的任务:

  • 等待新的客户端连接
  • 读取已连接客户端发来的消息并回复
  • 断开并移除连接异常的客户端

本例程中客户端的任务:

  • 创建5个客户端,并使每个客户端都成功连接服务端
  • 间隔1秒,发送消息告知服务端自己的套接字
  • 通信次数达到10次时,断开当前连接
  • 处于未连接状态时自动进行服务端重连

TCP协议服务端例程实现

// tpcserver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define MAX_CLIENT_CNT    10typedef struct
{int socket;int state;int cnt;
} TcpClient;typedef struct
{TcpClient	s[10];        int    		count;
} SocketArray;void msleep(int msecs);
int  addSocket(SocketArray *array, int socket);
int  delSocket(SocketArray *array, int socket);
int  getOneServerSocket(const char *ip, int port);int main(int argc, char *argv[])
{int rc, rxn, txn, srvfd, port;char ip[32] = {0};int i, maxfd;fd_set readfds;SocketArray sArray;bzero(&sArray, sizeof(sArray));char rxBuffer[1024] = {0};char txBuffer[1024] = {0};if (argc != 3){printf("please input correct arguments:\n");printf("\ttcpserver ip port\n\n");return -1;}// 解析ip和portstrcpy(ip, argv[1]);port = atoi(argv[2]);printf("ip: %s, port: %d\n", ip, port);// 创建套接字srvfd = getOneServerSocket(ip, port);// 循环非阻塞读取套接字上的数据while (1){maxfd = 0;FD_ZERO(&readfds);// 将服务端套接字加入select队列FD_SET(srvfd, &readfds);if (srvfd > maxfd)maxfd = srvfd;// 将所有已连接客户端的套接字加入select队列for (i=0; i<sArray.count; i++){FD_SET(sArray.s[i].socket, &readfds);if (sArray.s[i].socket > maxfd)maxfd = sArray.s[i].socket;}// 非阻塞等待套接字传来数据struct timeval timeout = {2, 0}; // 2sif (select(maxfd+1, &readfds, NULL, NULL, &timeout) <= 0){msleep(5);continue;}// 先确认监听套接字if (FD_ISSET(srvfd, &readfds)){int newfd, addrlen;struct sockaddr_in naddr;addrlen = sizeof(naddr);newfd = accept(srvfd, (struct sockaddr*)&naddr, &addrlen);if (newfd == -1){perror("accept");}else{printf("add new client[%s:%d], socket: %d\n", inet_ntoa(naddr.sin_addr), ntohs(naddr.sin_port), newfd);addSocket(&sArray, newfd);}}// 再确认客户端套接字for (i=0; i<sArray.count; i++){if (FD_ISSET(sArray.s[i].socket, &readfds)){bzero(rxBuffer, sizeof(rxBuffer));rxn = recv(sArray.s[i].socket, rxBuffer, sizeof(rxBuffer)-1, 0);if (rxn <= 0){printf("socket exception, socket: %d\n", sArray.s[i].socket);delSocket(&sArray, sArray.s[i].socket);continue;}printf("client[%d]: %s\n", sArray.s[i].socket, rxBuffer);bzero(txBuffer, sizeof(txBuffer));sprintf(txBuffer, "server reply client[%d]: %s", sArray.s[i].socket, rxBuffer);txn = send(sArray.s[i].socket, txBuffer, strlen(txBuffer), 0);if (txn <= 0){printf("socket exception, socket: %d\n", sArray.s[i].socket);delSocket(&sArray, sArray.s[i].socket);continue;}}}}for (i=0; i<sArray.count; i++)close(sArray.s[i].socket);close(srvfd);return 0;
}void msleep(int msecs)
{struct timeval stoptime;stoptime.tv_sec  = (int)(msecs/1000);stoptime.tv_usec = (int)(msecs%1000)*1000;select(0, 0, 0, 0, &stoptime);
}int  addSocket(SocketArray *array, int socket)
{if (array->count >= MAX_CLIENT_CNT){printf("The number of clients has reached the maximum limit(%d)\n", MAX_CLIENT_CNT);return -1;}int i, exists=0;for (i=0; i<array->count; i++){if (array->s[i].socket == socket){exists = 1;break;}}if (exists == 1){printf("client exists, socket: %d, index: %d\n", array->s[i].socket, i);return socket;}array->s[array->count].socket = socket;array->count += 1;printf("add client[%d], client count: %d\n", array->s[array->count].socket, array->count);return socket;
}int  delSocket(SocketArray *array, int socket)
{if (array->count <= 0){printf("No client\n");return -1;}int i;SocketArray tmpArr;bzero(&tmpArr, sizeof(tmpArr));for (i=0; i<array->count; i++){if (array->s[i].socket == socket){printf("remove client, socket: %d\n", socket);close(socket);continue;}tmpArr.s[tmpArr.count].socket = array->s[i].socket;tmpArr.count += 1;}memset(array, 0, sizeof(SocketArray));memcpy(array, &tmpArr, sizeof(tmpArr));return socket;
}int getOneServerSocket(const char *ip, int port)
{int rc, srvfd, reused, timeout;struct sockaddr_in addr;srvfd = socket(AF_INET, SOCK_STREAM, 0);if (srvfd == -1){perror("create socket");exit(-1);}// 设置端口复用reused = 1;rc = setsockopt(srvfd, SOL_SOCKET, SO_REUSEADDR, &reused, sizeof(reused));if (rc == -1){perror("SO_REUSEDADDR");goto EXIT;}// 设置发送超时限制timeout = 1000; // 1秒setsockopt(srvfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));if (rc == -1){perror("SO_SNDTIMEO");goto EXIT;}// 套接字绑定本地的ip和portaddr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(ip);bzero(addr.sin_zero, sizeof(addr.sin_zero));rc = bind(srvfd, (struct sockaddr*)&addr, sizeof(addr));if (rc == -1){perror("bind");goto EXIT;}// 监听套接字rc = listen(srvfd, 10);if (rc == -1){perror("listen");goto EXIT;}return srvfd;EXIT:close(srvfd);exit(-1);
}

###TCP协议客户端例程

// tcpclient.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define MAX_CLIENT_CNT    5
#define OFFLINE            0
#define ONLINE            1
#define MAX_MSG_SEND    10typedef struct
{int socket;int state;int cnt;
} TcpClient;typedef struct
{TcpClient     s[10];int         count;
} SocketArray;void msleep(int msecs);
int  addSocket(SocketArray *array, int socket);
int  delSocket(SocketArray *array, int socket);
int  getOneClientSocket(const char *ip, int port);
void setClientState(SocketArray *array, int fd, int state);
int  connectToServer(int fd, const char *ip, int port);int main(int argc, char *argv[])
{int rc, clifd, rxn, txn, port;char ip[32] = {0};int i, j, maxfd;fd_set readfds;SocketArray sArray;char rxBuffer[1024] = {0};char txBuffer[1024] = {0};if (argc != 3){printf("please input correct arguments:\n");printf("\ttcpclient ip port\n\n");return -1;}// 解析ip和portstrcpy(ip, argv[1]);port = atoi(argv[2]);printf("ip: %s, port: %d\n", ip, port);while (1){bzero(&sArray, sizeof(sArray));// 创建 MAX_CLIENT_CNT 个客户端for (i=0; i<MAX_CLIENT_CNT; i++){clifd = getOneClientSocket(ip, port);if (clifd == -1)continue;printf("create client, socket: %d\n", clifd);addSocket(&sArray, clifd);}// 所有离线客户端连接服务端for (i=0; i<sArray.count; i++){if (sArray.s[i].state == OFFLINE){rc = connectToServer(sArray.s[i].socket, ip, port);if (rc == 0)setClientState(&sArray, sArray.s[i].socket, ONLINE);elsesetClientState(&sArray, sArray.s[i].socket, OFFLINE);}}// 所有在线客户端主动向服务端打招呼for (i=0; i<sArray.count; i++){if (sArray.s[i].state == ONLINE){bzero(txBuffer, sizeof(txBuffer));sprintf(txBuffer, "Hello, i'm client[%d], i will disconnect after sending data %d times", sArray.s[i].socket, MAX_MSG_SEND-sArray.s[i].cnt);txn = send(sArray.s[i].socket, txBuffer, strlen(txBuffer), 0);if (txn <= 0){printf("socket exception, socket: %d\n", sArray.s[i].socket);setClientState(&sArray, sArray.s[i].socket, OFFLINE);continue;}sArray.s[i].cnt += 1;}msleep(100 * i);}// 连接成功的客户端循环执行任务while (1){j = 0;for (i=0; i<sArray.count; i++){if (sArray.s[i].state == OFFLINE)close(sArray.s[i].socket);elsej++;}sArray.count = j;if (sArray.count <= 0){printf("No connected clients\n");break;}maxfd = 0;FD_ZERO(&readfds);// 将所有已连接客户端的套接字加入select队列for (i=0; i<sArray.count; i++){if (sArray.s[i].state == OFFLINE)continue;FD_SET(sArray.s[i].socket, &readfds);if (sArray.s[i].socket > maxfd)maxfd = sArray.s[i].socket;}// 非阻塞等待套接字传来数据struct timeval timeout = {2, 0}; // 2sif (select(maxfd+1, &readfds, NULL, NULL, &timeout) <= 0){msleep(5);continue;}// 处理已连接套接字上的消息及数据for (i=0; i<sArray.count; i++){if (sArray.s[i].state == OFFLINE)continue;if (FD_ISSET(sArray.s[i].socket, &readfds)){// 发送消息数量达到 MAX_MSG_SEND 的客户端主动断开连接if (sArray.s[i].cnt >= MAX_MSG_SEND){printf("i'm client[%d], i will disconnect now\n", sArray.s[i].socket);setClientState(&sArray, sArray.s[i].socket, OFFLINE);continue;}bzero(rxBuffer, sizeof(rxBuffer));rxn = recv(sArray.s[i].socket, rxBuffer, sizeof(rxBuffer)-1, 0);if (rxn <= 0){printf("socket exception, socket: %d\n", sArray.s[i].socket);setClientState(&sArray, sArray.s[i].socket, OFFLINE);continue;}printf("client[%d] recv: %s\n", sArray.s[i].socket, rxBuffer);bzero(txBuffer, sizeof(txBuffer));sprintf(txBuffer, "Hello, i'm client[%d], i will disconnect after sending data %d times", sArray.s[i].socket, MAX_MSG_SEND-sArray.s[i].cnt);txn = send(sArray.s[i].socket, txBuffer, strlen(txBuffer)+1, 0);if (txn <= 0){printf("socket exception, socket: %d\n", sArray.s[i].socket);setClientState(&sArray, sArray.s[i].socket, OFFLINE);continue;}sArray.s[i].cnt += 1;}msleep(100 * i);}msleep(1000);}msleep(1000);}for (i=0; i<sArray.count; i++){close(sArray.s[i].socket);}return 0;
}void msleep(int msecs)
{struct timeval stoptime;stoptime.tv_sec  = (int)(msecs/1000);stoptime.tv_usec = (int)(msecs%1000)*1000;select(0, 0, 0, 0, &stoptime);
}int  addSocket(SocketArray *array, int socket)
{if (array->count >= MAX_CLIENT_CNT){printf("The number of clients has reached the maximum limit(%d)\n", MAX_CLIENT_CNT);return -1;}int i, exists=0;for (i=0; i<array->count; i++){if (array->s[i].socket == socket){exists = 1;break;}}if (exists == 1){printf("client exists, socket: %d, index: %d\n", socket, i);return socket;}array->s[array->count].socket = socket;array->s[array->count].state = OFFLINE;array->count += 1;printf("add client[%d], client count: %d\n", array->s[i].socket, array->count);return socket;
}int  delSocket(SocketArray *array, int socket)
{if (array->count <= 0){printf("No client\n");return -1;}int i;SocketArray tmpArr;bzero(&tmpArr, sizeof(tmpArr));for (i=0; i<array->count; i++){if (array->s[i].socket == socket){printf("remove client, socket: %d\n", socket);close(socket);continue;}tmpArr.s[tmpArr.count].socket = array->s[i].socket;tmpArr.s[tmpArr.count].state = array->s[i].state;tmpArr.count += 1;}memset(array, 0, sizeof(SocketArray));memcpy(array, &tmpArr, sizeof(tmpArr));return socket;
}int  getOneClientSocket(const char *ip, int port)
{int rc, clifd, reused, timeout;clifd = socket(AF_INET, SOCK_STREAM, 0);if (clifd == -1){perror("create socket");return -1;}// 设置端口复用reused = 1;rc = setsockopt(clifd, SOL_SOCKET, SO_REUSEADDR, &reused, sizeof(reused));if (rc == -1){perror("SO_REUSEDADDR");goto EXIT;}// 设置发送超时限制timeout = 1000; // 1秒setsockopt(clifd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));if (rc == -1){perror("SO_SNDTIMEO");goto EXIT;}return clifd;EXIT:close(clifd);return -1;
}int  connectToServer(int fd, const char *ip, int port)
{int rc;struct sockaddr_in addr;// 套接字绑定服务端的ip和portaddr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(ip);bzero(addr.sin_zero, sizeof(addr.sin_zero));// 连接服务端rc = connect(fd, (struct sockaddr*)&addr, sizeof(addr));if (rc == -1){printf("failed to connect server[%s:%d], socket: %d\n", ip, port, fd);return -1;}printf("client connect succeed, socket: %d\n", fd);return 0;
}void setClientState(SocketArray *array, int fd, int state)
{int i;for (i=0; i<array->count; i++){if (array->s[i].socket == fd){array->s[i].state = state;break;}}
}

例程编译及运行

TCP服务端例程编译及运行结果
#假设主机ip为192.168.201.28
$ gcc tcpserver.c -o tcpserver
$ ./tcpserver 0.0.0.0 66666
ip: 0.0.0.0, port: 66666
add new client[192.168.146.128:57654], socket: 4
add new client[192.168.146.128:57655], socket: 5
add new client[192.168.146.128:57656], socket: 6
add new client[192.168.146.128:57657], socket: 7
add new client[192.168.146.128:57658], socket: 8
client[4]: Hello, i'm client[3], i will disconnect after sending data 10 times
client[5]: Hello, i'm client[4], i will disconnect after sending data 10 times
client[6]: Hello, i'm client[5], i will disconnect after sending data 10 times
client[7]: Hello, i'm client[6], i will disconnect after sending data 10 times
client[8]: Hello, i'm client[7], i will disconnect after sending data 10 times
client[4]: Hello, i'm client[3], i will disconnect after sending data 9 times
client[5]: Hello, i'm client[4], i will disconnect after sending data 9 times
client[6]: Hello, i'm client[5], i will disconnect after sending data 9 times
client[7]: Hello, i'm client[6], i will disconnect after sending data 9 times
client[8]: Hello, i'm client[7], i will disconnect after sending data 9 times
client[4]: Hello, i'm client[3], i will disconnect after sending data 8 times
client[5]: Hello, i'm client[4], i will disconnect after sending data 8 times
client[6]: Hello, i'm client[5], i will disconnect after sending data 8 times
client[7]: Hello, i'm client[6], i will disconnect after sending data 8 times
client[8]: Hello, i'm client[7], i will disconnect after sending data 8 times
...
client[4]: Hello, i'm client[3], i will disconnect after sending data 1 times
client[5]: Hello, i'm client[4], i will disconnect after sending data 1 times
client[6]: Hello, i'm client[5], i will disconnect after sending data 1 times
client[7]: Hello, i'm client[6], i will disconnect after sending data 1 times
client[8]: Hello, i'm client[7], i will disconnect after sending data 1 times
socket exception, socket: 4
remove client, socket: 4
socket exception, socket: 6
remove client, socket: 6
socket exception, socket: 8
remove client, socket: 8
socket exception, socket: 5
remove client, socket: 5
socket exception, socket: 7
remove client, socket: 7
add new client[192.168.146.128:57855], socket: 4
add new client[192.168.146.128:57856], socket: 5
add new client[192.168.146.128:57857], socket: 6
add new client[192.168.146.128:57858], socket: 7
add new client[192.168.146.128:57859], socket: 8
client[4]: Hello, i'm client[3], i will disconnect after sending data 10 times
client[5]: Hello, i'm client[4], i will disconnect after sending data 10 times
client[6]: Hello, i'm client[5], i will disconnect after sending data 10 times
client[7]: Hello, i'm client[6], i will disconnect after sending data 10 times
client[8]: Hello, i'm client[7], i will disconnect after sending data 10 times
TCP客户端例程编译及运行结果
# 新打开一个终端
$ gcc tcpclient.c -o tcpclient
$ ./tcpclient 192.168.201.28 66666ip: 192.168.146.128, port: 66666
create client, socket: 3
add client[3], client count: 1
create client, socket: 4
add client[4], client count: 2
create client, socket: 5
add client[5], client count: 3
create client, socket: 6
add client[6], client count: 4
create client, socket: 7
add client[7], client count: 5
client connect succeed, socket: 3
client connect succeed, socket: 4
client connect succeed, socket: 5
client connect succeed, socket: 6
client connect succeed, socket: 7
client[3] recv: server reply client[4]: Hello, i'm client[3], i will disconnect after sending data 10 times
client[4] recv: server reply client[5]: Hello, i'm client[4], i will disconnect after sending data 10 times
client[5] recv: server reply client[6]: Hello, i'm client[5], i will disconnect after sending data 10 times
client[6] recv: server reply client[7]: Hello, i'm client[6], i will disconnect after sending data 10 times
client[7] recv: server reply client[8]: Hello, i'm client[7], i will disconnect after sending data 10 times
client[3] recv: server reply client[4]: Hello, i'm client[3], i will disconnect after sending data 9 times
client[4] recv: server reply client[5]: Hello, i'm client[4], i will disconnect after sending data 9 times
client[5] recv: server reply client[6]: Hello, i'm client[5], i will disconnect after sending data 9 times
client[6] recv: server reply client[7]: Hello, i'm client[6], i will disconnect after sending data 9 times
client[7] recv: server reply client[8]: Hello, i'm client[7], i will disconnect after sending data 9 times
...
client[3] recv: server reply client[4]: Hello, i'm client[3], i will disconnect after sending data 2 times
client[4] recv: server reply client[5]: Hello, i'm client[4], i will disconnect after sending data 2 times
client[5] recv: server reply client[6]: Hello, i'm client[5], i will disconnect after sending data 2 times
client[6] recv: server reply client[7]: Hello, i'm client[6], i will disconnect after sending data 2 times
client[7] recv: server reply client[8]: Hello, i'm client[7], i will disconnect after sending data 2 times
i'm client[3], i will disconnect now
i'm client[4], i will disconnect now
i'm client[5], i will disconnect now
i'm client[6], i will disconnect now
i'm client[7], i will disconnect now
No connected clients
create client, socket: 3
add client[3], client count: 1
create client, socket: 4
add client[4], client count: 2
create client, socket: 5
add client[5], client count: 3
create client, socket: 6
add client[6], client count: 4
create client, socket: 7
add client[7], client count: 5
client connect succeed, socket: 3
client connect succeed, socket: 4
client connect succeed, socket: 5
client connect succeed, socket: 6
client connect succeed, socket: 7
client[3] recv: server reply client[4]: Hello, i'm client[3], i will disconnect after sending data 10 times
client[4] recv: server reply client[5]: Hello, i'm client[4], i will disconnect after sending data 10 times
client[5] recv: server reply client[6]: Hello, i'm client[5], i will disconnect after sending data 10 times
client[6] recv: server reply client[7]: Hello, i'm client[6], i will disconnect after sending data 10 times
client[7] recv: server reply client[8]: Hello, i'm client[7], i will disconnect after sending data 10 times

网络编程之TCP协议例程小结

本节展示的例程只是基础的通信框架,还未嵌套较为完善的通信协议,感兴趣的小伙伴可以自行补充完善(期待大家的分享-)。后期有时间的话,我准备加入Modbus协议,欢迎小伙伴们积极收藏关注私信交流!

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

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

相关文章

【VerilogVCS仿真_2023.11.15】

HDL&#xff1a;硬件描述语言&#xff0c;并发&#xff0c;时序RTL&#xff1a;寄存器传输级语言 Verilog和VHDL的区别&#xff1a;VHDL侧重于系统级描述——系统级设计人员所采用&#xff0c;Verilog侧重于模块行为的抽象描述——电路级设计人员 前端&#xff1a;系统级、算法…

linux上编写进度条

目录 一、预备的两个小知识1、缓冲区2、回车与换行 二、倒计时程序三、编写入门的进度条四、编写一个正式的五、模拟实现和下载速度相关的进度条 一、预备的两个小知识 1、缓冲区 首先认识一下缓冲区&#xff1a;先写一个.c文件如下&#xff1a; 我们执行一下这个程序时&…

【产品应用】一体化伺服电机在摆轮分拣机中的应用

随着物流和制造业的快速发展&#xff0c;分拣机的应用越来越广泛。摆轮分拣机作为一种常见的分拣设备&#xff0c;具有高效、准确、灵活等特点&#xff0c;被广泛应用于各类物流分拣场景。而一体化伺服电机在摆轮分拣机中的应用&#xff0c;为分拣机的性能提升和优化提供了新的…

专业视频剪辑利器Final Cut Pro for Mac,让你的创意无限发挥

在如今的数字时代&#xff0c;视频内容已经成为人们生活中不可或缺的一部分。无论是在社交媒体上分享生活点滴&#xff0c;还是在工作中制作专业的营销视频&#xff0c;我们都希望能够以高质量、高效率地进行视频剪辑和制作。而Final Cut Pro for Mac作为一款专业级的视频剪辑软…

6.5 Windows驱动开发:内核枚举PspCidTable句柄表

在 Windows 操作系统内核中&#xff0c;PspCidTable 通常是与进程&#xff08;Process&#xff09;管理相关的数据结构之一。它与进程的标识和管理有关&#xff0c;每个进程都有一个唯一的标识符&#xff0c;称为进程 ID&#xff08;PID&#xff09;。与之相关的是客户端 ID&am…

【蓝桥杯软件赛 零基础备赛20周】第6周——栈

文章目录 1. 基本数据结构概述1.1 数据结构和算法的关系1.2 线性数据结构概述1.3 二叉树简介 2. 栈2.1 手写栈2.2 CSTL栈2.3 Java 栈2.4 Python栈 3 习题 1. 基本数据结构概述 很多计算机教材提到&#xff1a;程序 数据结构 算法。 “以数据结构为弓&#xff0c;以算法为箭”…

uniapp uview u-input在app(运行在安卓基座上)上不能动态控制type类型(显隐密码)

开发密码显隐功能时&#xff0c;在浏览器h5上功能是没问题的 <view class"login-item-input"><u-input:type"showPassWord ? password : text"style"background: #ecf0f8"placeholder"请输入密码"border"surround&quo…

麻吉POS集成:如何无代码开发实现电商平台和CRM系统的高效连接

麻吉POS集成的前沿技术&#xff1a;无代码开发 在竞争激烈的电商市场中&#xff0c;商家们急需一种高效且易于操作的技术手段来实现系统间的快速连接与集成。麻吉POS以其前沿的无代码开发技术&#xff0c;让这一需求成为可能。无代码开发是一种允许用户通过图形用户界面进行编…

LiteOS内存管理:TLSF算法

问题背景 TLSF算法主要是面向实时操作系统提出的&#xff0c;对于RTOS而言&#xff0c;执行时间的确定性是最根本的&#xff0c;然而传统的动态内存分配器&#xff08;DMA&#xff0c;Dynamic Memory Allocator&#xff09;存在两个主要问题&#xff1a; 最坏情况执行时间不确…

【LeetCode】栈和队列OJ题---C语言版

栈和队列OJ题 1.括号匹配问题&#xff08;1&#xff09;题目描述&#xff1a;&#xff08;2&#xff09;思路表述&#xff1a;&#xff08;3&#xff09;代码实现&#xff1a; 2.用队列实现栈&#xff08;1&#xff09;题目描述&#xff1a;&#xff08;2&#xff09;思路表述&…

Python学习路线 - Python语言基础入门 - 准备工作

Python学习路线 - Python语言基础入门 - 准备工作 初识PythonPython的优点 什么是编程语言Python环境安装Windows系统Python安装Python验证 MacOS系统Linux系统 第一个Python程序常见问题 Python解释器Python解释器概念Python解释器存放位置Python解释器运行".py"文件…

vue3请求代理proxy中pathRewrite失效

问题引入 在vue3配置请求代理proxy的时候pathRewrite失效。 有这样一个例子&#xff0c;作用是为了把所有以/api开头的请求代理到后端的路径和端口上&#xff0c;在vue.config.js配置文件中 设置了代理跨域和默认端口。但是重新运行之后发现端口是改了&#xff0c;但是路径仍然…

【工作生活】汽车ECU开发内容简介

目录 1. 目标 2. 要分享什么 3.1 行业知识 3.1.1车载行业知识&#xff1a; 3.1.2项目&#xff1a; 3.1.3开发测试工具&#xff1a; 3.2 硬件平台 3.3 基础知识 3.4 工作生活 3. 我们是谁 1. 目标 随着新能源汽车的快速崛起&#xff0c;汽车电子行业开始快速发展&…

Redis数据结构之跳表

跳表是一种有序的数据结构&#xff0c;它通过在每个节点中维持多个指向其他节点的指针&#xff0c;从而达到快速访问节点的目的。其核心思想就是通过建立多级索引来实现空间换时间。 在Redis中&#xff0c;使用跳表作为Zset的一种底层实现之一&#xff0c;这也是跳表在Redis中的…

SpringBoot 集成 ChatGPT,实战附源码

1 前言 在本文中&#xff0c;我们将探索在 Spring Boot 应用程序中调用 OpenAI ChatGPT API 的过程。我们的目标是开发一个 Spring Boot 应用程序&#xff0c;能够利用 OpenAI ChatGPT API 生成对给定提示的响应。 您可能熟悉 ChatGPT 中的术语“提示”。在 ChatGPT 或类似语…

如何本地搭建个人hMailServer邮件服务并实现远程发送邮件

文章目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpola…

C语言中一些特殊字符的输出

目录 %的介绍 斜杠与反斜杠 转义字符 %的介绍 int a1; 1、printf(’’%d’’,a);//输出1 2、printf(’’%%d’’,a);//输出%d 3、printf&#xff08;’’%%%d ‘’,a)//输出%1 C语言中&#xff0c;%也是转义符&#xff0c;%%相当于% 斜杠与反斜杠 首先需要明白…

学习TypeScrip1(基本类型)

TS是JS的超集&#xff0c;所以JS基础的类型都包含在内起步安装 npm install typescript -g运行tsc 文件名 nodejs 环境执行 ts npm i types/node --save-dev &#xff08;node环境支持的依赖必装&#xff09; npm i ts-node --g 基础类型&#xff1a;Boolean、Number、Str…

持续集成部署-k8s-高级调度-InitC:初始化容器的概念和使用

持续集成部署-k8s-高级调度-InitC&#xff1a;初始化容器的概念和使用 1. Init Container&#xff08;初始化容器&#xff09;是什么&#xff1f;2. Init Container 的简单使用 1. Init Container&#xff08;初始化容器&#xff09;是什么&#xff1f; 在Kubernetes中&#x…

VLAN间路由详细讲解

本次实验拓扑的主要概述以及设计到的相关技术 VLAN技术&#xff1a; VLAN&#xff08;Virtual Local Area Network&#xff09;即虚拟局域网&#xff0c;是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。 每个VLAN是一个广播域&#xff0c;VLAN内的主机间可以直…