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

通信安全之数据加密

        数据安全的需求如今越来越重要,本篇简单举例给日常的TCP/UDP通信加密,至少能让想干坏事的崽犯罪的成本更高一些(如果会一些BPF的,可能难不住这些崽),能让我们的数据更安全一点。

经典TCP socket编程

下面为大家常见的TCP socket编程示例:

客户端
/* client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>  
#include <sys/types.h>   
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
//#include "myssl.h"int main(int argc, char *argv[])
{// 定义相关变量int sockfd;struct sockaddr_in serv_addr;char buf[1024] = {0};const char *greeting = "Hello from client";if(argc < 2){printf("please input the ip of the server..\n");return -1;}//获取并初始化服务端地址serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8080);if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0){fprintf(stderr, "inet_pton failed[%d].\n", errno);return -1;}// 创建socketif((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "create socket failed[%d].\n", errno);return -1;}// 连接到服务器if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){fprintf(stderr, "connect failed[%d].\n", errno);return -1;}// 发送数据if(write(sockfd, greeting, strlen(greeting)) < 0){fprintf(stderr, "write failed[%d].\n", errno);return -1;}// 接收数据if(read(sockfd, buf, 1024) < 0){fprintf(stderr, "read failed[%d].\n", errno);return -1;}printf("received message:%s\n", buf);close(sockfd);
}
服务端
/* server.c */
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#include <sys/types.h>   
#include <sys/socket.h>  
#include <netinet/in.h>
#include <errno.h>
//#include "myssl.h"#define MAX_CNT 5int main(int argc, char *argv[])
{// 定义相关变量int server_fd, new_socket;int opt = 1; struct sockaddr_in serv_addr, cli_addr;socklen_t cli_addr_len;char buf[1024] = {0};const char *greeting = "Hello from server";// 创建socket文件描述符if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "create socket failed[%d].\n", errno);return -1;}// 设置socket选项if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {  fprintf(stderr, "set socket failed[%d].\n", errno);return -1;  }// 绑定socket到指定端口和地址memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(8080);if(bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){fprintf(stderr, "create bind failed[%d].\n", errno);return -1;}// 监听if(listen(server_fd, MAX_CNT) < 0){fprintf(stderr, "listen failed[%d].\n", errno);return -1;}// 接受客户端连接请求memset(&cli_addr, 0, sizeof(cli_addr));cli_addr_len = sizeof(cli_addr);if((new_socket = accept(server_fd, (struct sockaddr *)&cli_addr, (socklen_t *)&cli_addr_len)) < 0 ){fprintf(stderr, "accept failed[%d].\n", errno);return -1;}printf("Client [%s-%d] connected.\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));// 接收数据if(read(new_socket, buf, 1024) < 0){fprintf(stderr, "read failed[%d].\n", errno);return -1;}printf("received message:%s\n", buf);// 发送数据if(write(new_socket, greeting, strlen(greeting)) < 0){fprintf(stderr, "write failed[%d].\n", errno);return -1;}// 关闭socketclose(new_socket);close(server_fd);printf("server closed.\n");return 0;
}

开启两个终端,运行结果如下:

数据加密方式TCP socket编程

封装加密初始化程序

        我们创建两个文件,一个为myssl.h,一个为对应的实现文件myssl.c,如下:

/* myssl.h */#ifndef __MYSSL_H_
#define __MYSSL_H_#include <openssl/ssl.h>typedef enum{SSL_MODE_SERVER,SSL_MODE_CLIENT
}SSL_MODE;//对象方法枚举SSL *init_ssl(char *cert_path, char *key_path, SSL_MODE mode, int fd);//初始化函数#endif
/* myssl.c */
#include <openssl/ssl.h>
#include <stdio.h>
#include <stdlib.h>
#include "myssl.h"SSL *init_ssl(char * cert_path, char * key_path, SSL_MODE mode, int fd)
{// 声明套件变量const SSL_METHOD *method;SSL_CTX *ctx;SSL *ssl = NULL;// 添加支持的算法,加载错误信息OpenSSL_add_all_algorithms();SSL_load_error_strings();// 获取对象方法// 不同版本的openssl对应的API也是有区别的,需要注意if(mode == SSL_MODE_SERVER){method = SSLv23_server_method();}else if(mode == SSL_MODE_CLIENT){method = SSLv23_client_method();}else{printf("unkown method\n");return NULL;}// 创建CTXctx = SSL_CTX_new(method);if(!ctx){printf("create SSL CTX failed.\n");return NULL;}// 读取证书(公钥)和密钥(私钥)if((SSL_CTX_use_certificate_file(ctx, cert_path, SSL_FILETYPE_PEM) <= 0)||(SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) <= 0)){printf("not found file\n");return NULL;}// 创建SSLssl = SSL_new(ctx);if(!ssl){printf("failed create SSL.\n");return NULL;}// 绑定套接字的文件描述符到SSL中if(SSL_set_fd(ssl, fd) == 0){printf("SSL set fd failed.\n");return NULL;}// 连接套接字if((mode == SSL_MODE_SERVER && SSL_connect(ssl) <= 0)||(mode == SSL_MODE_CLIENT && SSL_connect(ssl) <= 0)){printf("failed handshake with ssl.\n");return NULL;}return ssl;
}

 修改经典socket编程代码

        我们来对上面的客户端和服务端程序做些修改,以期使得变成加密的套接字通信。

客户端
/* client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>  
#include <sys/types.h>   
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include "myssl.h"int main(int argc, char *argv[])
{// 定义相关变量int sockfd;struct sockaddr_in serv_addr;char buf[1024] = {0};const char *greeting = "Hello from client";if(argc < 2){printf("please input the ip of the server..\n");return -1;}//获取并初始化服务端地址serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8080);if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0){fprintf(stderr, "inet_pton failed[%d].\n", errno);return -1;}// 创建socketif((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "create socket failed[%d].\n", errno);return -1;}// 连接到服务器if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){fprintf(stderr, "connect failed[%d].\n", errno);return -1;}// 初始化加密函数SSL *ssl = init_ssl("./cert.pem", "./key.pem", SSL_MODE_CLIENT, sockfd);// 发送数据if(SSL_write(ssl, greeting, strlen(greeting)) < 0)	//if(write(sockfd, greeting, strlen(greeting)) < 0){fprintf(stderr, "write failed[%d].\n", errno);return -1;}// 接收数据if(SSL_read(ssl, buf, 1024) < 0) //if(read(sockfd, buf, 1024) < 0){fprintf(stderr, "read failed[%d].\n", errno);return -1;}printf("received message:%s\n", buf);close(sockfd);SSL_shutdown(ssl);SSL_free(ssl);
}
服务端
/* server.c */#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#include <sys/types.h>   
#include <sys/socket.h>  
#include <netinet/in.h>
#include <errno.h>
//#include "myssl.h"#define MAX_CNT 5int main(int argc, char *argv[])
{// 定义相关变量int server_fd, new_socket;int opt = 1;struct sockaddr_in serv_addr, cli_addr;socklen_t cli_addr_len;char buf[1024] = {0};const char *greeting = "Hello from server";// 创建socket文件描述符if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){fprintf(stderr, "create socket failed[%d].\n", errno);return -1;}// 设置socket选项if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {  fprintf(stderr, "set socket failed[%d].\n", errno);return -1;  } // 绑定socket到指定端口和地址memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(8080);if(bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){fprintf(stderr, "create bind failed[%d].\n", errno);return -1;}// 监听if(listen(server_fd, MAX_CNT) < 0){fprintf(stderr, "listen failed[%d].\n", errno);return -1;}// 接受客户端连接请求memset(&cli_addr, 0, sizeof(cli_addr));cli_addr_len = sizeof(cli_addr);if((new_socket = accept(server_fd, (struct sockaddr *)&cli_addr, (socklen_t *)&cli_addr_len)) < 0 ){fprintf(stderr, "accept failed[%d].\n", errno);return -1;}		printf("Client [%s-%d] connected.\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));// 初始化加密函数SSL *ssl = init_ssl("./cert.pem", "./key.pem", SSL_MODE_SERVER, new_socket);// 接收数据if(SSL_read(ssl, buf, 1024) < 0) //if(read(new_socket, buf, 1024) < 0){fprintf(stderr, "read failed[%d].\n", errno);return -1;}printf("received message:%s\n", buf);// 发送数据if(SSL_write(ssl, greeting, strlen(greeting)) < 0) //if(write(new_socket, greeting, strlen(greeting)) < 0){fprintf(stderr, "write failed[%d].\n", errno);return -1;}// 关闭socketclose(new_socket);close(server_fd);SSL_shutdown(ssl);SSL_free(ssl);printf("server closed.\n");return 0;
}
Makefile

        为了方便总体编译,我们创建一个Makefile,内容如下:

LIBS=-lssl -lcrypto
all:gcc -o server server.c myssl.c $(LIBS)gcc -o client client.c myssl.c $(LIBS)
clean:rm -rf server client
证书、密钥

        为方便测试,我们利用openssl生成密钥key.pem及公钥文件cert.pem,命令如下:

密钥

$openssl genpkey -algorithm RSA -out key.pem

公钥(利用密钥生成,生成之前需要根据提示输入一些地址公司等信息)

$sudo openssl req -new -x509 -key key.pem -out cert.pem -days 3650

注意openssl的版本程序中用到的和命令行的这个要保持一致,结果如下:

编译问题

        在终端执行make命令,如果出现找不到<openssl/ssl.h>,那么你的系统环境可能没有安装openssl开发库,我们可以通过下面命令安装:

sudo apt-get update  
sudo apt-get install libssl-dev

安装完毕后,<openssl/ssl.h>应该可以在/usr/include/openssl/目录中找到。

如果安装成功之后还是报找不到头文件的错误,通过下面命令检查定位头文件所在位置:

dpkg -L libssl-dev | grep ssl.h

如果你确定环境中有这个头文件而其他方法都不行的话,可以试试手动添加路径指定,如下:

gcc -o myprogram myprogram.c -I/usr/include/openssl -lssl -lcrypto

如果方法都试遍了,我们只能尝试卸掉重新安装。

sudo apt-get remove --purge libssl-dev  
sudo apt-get update  
sudo apt-get install libssl-dev

如果报找不到openssl的某些API 或相关问题,此时则需参考下面的流程对源码做出修改。

补充

        因为openssl每个跨级的版本(0.9/1.0/3.0)API的变动较大(有些遗弃有些修改),兼容性不好,我们编写的应用源代码可能会需要做些修改(如果使用的openssl变动了版本)。如果没有openssl的源码,系统中只有库文件,我们可以通过objdump命令来检索其用的哪些API,方便我们替换修改,举例:

$objdump -Tt libxxx.so | grep SSL*

类似返回如下结果:

参考

B站爱吃甜食的老猫的视频

相关文章:

通信安全之数据加密

数据安全的需求如今越来越重要&#xff0c;本篇简单举例给日常的TCP/UDP通信加密&#xff0c;至少能让想干坏事的崽犯罪的成本更高一些&#xff08;如果会一些BPF的&#xff0c;可能难不住这些崽&#xff09;&#xff0c;能让我们的数据更安全一点。 经典TCP socket编程 下面…...

花一分钟简单认识 CSS 中的规则 —— 级联层 @layer

layer 简介&#xff1a; 声明级联层时&#xff0c;越靠后优先级越高。不属于任何级联层的样式&#xff0c;将自成一层匿名级联层&#xff0c;并置于所有层之后 —— 级别最高。 用法一&#xff1a;在同一文件中 layer base, special; layer special {/* 优先 */li { color: …...

K8s学习三(Pod与探针)

深入学习Pod Pod配置文件 写一个自己的配置文件,nginx-po.yaml apiVersion: v1 #api文档版本 kind: Pod #资源类型对象&#xff0c;也可以配置为像Development&#xff0c;StatefulSet这一类的对象 metadata: # Pod相关的元数据&#xff0c;用于描述Pod的数据name: nginx-po…...

leetcode - 678. Valid Parenthesis String

Description Given a string s containing only three types of characters: ‘(’, ‘)’ and ‘*’, return true if s is valid. The following rules define a valid string: Any left parenthesis ( must have a corresponding right parenthesis ). Any right parenth…...

索尼相机照片清理软件

在使用索尼相机拍摄照片的时候有时我们需要同时拍摄JPG格式和RAW格式&#xff0c;这在后期选图的时候给我们带来一些麻烦。我们固然可以选用Br来管理照片&#xff0c;但是现在我们可以有一个更轻量的软件&#xff08;8.8MB&#xff09;来做到一部分功能。 我们将照片从SD卡导出…...

比赛记录:Codeforces Global Round 25 A~E (猜猜题场)

传送门:CF [前题提要]:其实这场打的不是很好.A题一个sb错误看不出来,50min后才过,B题上来就Wa了一发,C题用了没必要的线段树,D题刚开始被60诈骗,一直在想按位考虑.幸好赛时猜出了E,然后又猜出来D,本来掉大分变成上大分…但是这场前几题大都是猜猜题,所以本来不想写题解的.但是…...

Windows系统安装OpenSSH结合VS Code远程ssh连接Ubuntu【内网穿透】

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-AwzyR2lkHKjD9HYl {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...

Svg Flow Editor 原生svg流程图编辑器(五)

系列文章 Svg Flow Editor 原生svg流程图编辑器&#xff08;一&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;二&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;三&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;四&#xf…...

数字晶体管选型参数,结构原理,工艺与注意问题总结

🏡《总目录》 目录 1,概述2,工作原理2.1,AND 门(与门),2.2,OR 门(或门):2.3,NOT 门(非门):2.4,NAND 门(与非门):2.5,NOR 门(或非门):3,结构特点3.1,TTL(Transistor-Transistor Logic)晶体管...

lua学习笔记9(字典的学习)

print("********************字典的学习***********************") a{["凌少"]"傻逼",["我"]"天才",["age"]24,["daihao"]114514,["8848"]20000} --访问单个变量 print(a["凌少"])…...

第六篇: 3.5 性能效果 (Performance)- IAB/MRC及《增强现实广告效果测量指南1.0》

​​​​​​​ 翻译计划 第一篇概述—IAB与MRC及《增强现实广告效果测量指南》之目录、适用范围及术语第二篇 广告效果测量定义和其他矩阵之- 3.1 广告印象&#xff08;AD Impression&#xff09;第三篇 广告效果测量定义和其他矩阵之- 3.2 可见性 &#xff08;Viewability…...

mysql学习笔记NO.2

Java操作数据库、表笔记 1.创建数据库 创建数据库的步骤如下&#xff1a; 导入所需的Java数据库连接驱动&#xff08;如MySQL驱动&#xff09;。使用JDBC连接到数据库。执行SQL语句创建数据库。 import java.sql.Connection; import java.sql.DriverManager; import java.…...

C++11:lambda表达式 包装器

C11&#xff1a;lambda表达式 & 包装器 lambda表达式包装器functionbind lambda表达式 在C98中&#xff0c;如果想对一个结构体数组使用sort排序&#xff0c;那么我们就需要自己些仿函数。 比如以下结构体&#xff1a; struct Goods {string _name; // 名字double _pric…...

Node.js HTTP/2 CONTINUATION 拒绝服务漏洞(CVE-2024-27983)

Node.js 是开源、跨平台的 JavaScript 运行时环境。CONTINUATION泛洪攻击被发现存在于多个HTTP/2协议实现中。 在受影响版本中&#xff0c;由于Node.js针对HTTP/2协议的实现不当&#xff0c;未正确处理多个CONTINUATION帧的情况&#xff0c;在node::http2::Http2Session::~Htt…...

YOLOV8 + 双目测距

YOLOV8 双目测距 1. 环境配置2. 测距流程和原理2.1 测距流程2.2 测距原理 3. 代码部分解析3.1 相机参数stereoconfig.py3.2 测距部分3.3 主代码yolov8-stereo.py 4. 实验结果4.1 测距4.2 测距跟踪4.3 测距跟踪分割4.4 视频展示 相关文章 1. YOLOv5双目测距&#xff08;python&…...

前端:SVG绘制流程图

效果 代码 html代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>SVG流程图示例</title><style>/* CSS 样式 */</style><script src"js/index.js"></script…...

【Linux系列】如何确定当前运行的是 RHEL 9 还是 RHEL 8?

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

vscode开发java的插件和配置

推荐插件 .vscode/extensions.json {"recommendations": ["redhat.fabric8-analytics","ms-azuretools.vscode-docker","vscjava.vscode-java-pack","eamodio.gitlens","obkoro1.korofileheader","redhat.j…...

Mysql启动报错:本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止

Mysql启动报错&#xff1a;本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止 文章目录 Mysql启动报错&#xff1a;本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止1. 备份mysql的data文件夹2. 重新构建 Wind…...

WPF程序添加托盘图标

程序添加托盘图标 UI层 //添加handycontrol的引用xmlns:hc"https://handyorg.github.io/handycontrol"//添加NotifyIcon图标 实现单击 双击 二级菜单点击功能<hc:NotifyIconText"通知"Token"Info"><hc:NotifyIcon.ContextMenu><…...

永磁同步电机基于SMC的SMO无传感器控制:速度环的新变革

本仿真才用滑膜控制器替换速度环控制器&#xff0c; 永磁同步电机基于smc的smo无传感器控制。在永磁同步电机&#xff08;PMSM&#xff09;的控制领域&#xff0c;一直以来人们都在不断探索更高效、精确的控制策略。今天咱们聊聊基于滑膜控制器&#xff08;SMC&#xff09;替换…...

如何计算 CSS 的优先级?

CSS 优先级&#xff08;也称为特异性或 Specificity&#xff09;决定了当多个样式规则应用于同一个元素时&#xff0c;哪一个规则会生效。 计算 CSS 优先级的核心规则如下&#xff1a; 1. 优先级计算权重&#xff08;特异性&#xff09; CSS 选择器的优先级通常用一个四位数的向…...

如何为LaTeX简历项目贡献代码:开源参与全流程指南

如何为LaTeX简历项目贡献代码&#xff1a;开源参与全流程指南 【免费下载链接】resume Software developer resume in Latex 项目地址: https://gitcode.com/gh_mirrors/res/resume 参与开源项目是提升技能、建立专业网络的绝佳方式。本文将以GitHub加速计划中的res/res…...

Spring Cloud Gateway + Nacos 2.2.0:手把手教你实现一个可动态调整的灰度发布过滤器

Spring Cloud Gateway与Nacos 2.2.0深度整合&#xff1a;构建企业级动态灰度发布体系 在微服务架构的演进过程中&#xff0c;灰度发布已成为保障服务稳定性的关键策略。传统灰度方案往往面临规则调整需要重启、策略变更滞后等痛点。本文将深入探讨如何利用Spring Cloud Gateway…...

小红书内容采集工具终极指南:如何5分钟掌握无水印下载技巧

小红书内容采集工具终极指南&#xff1a;如何5分钟掌握无水印下载技巧 【免费下载链接】XHS-Downloader 免费&#xff1b;轻量&#xff1b;开源&#xff0c;基于 AIOHTTP 模块实现的小红书图文/视频作品采集工具 项目地址: https://gitcode.com/gh_mirrors/xh/XHS-Downloader…...

ComfyUI-WanVideoWrapper完整教程:三步搭建AI视频生成工作站

ComfyUI-WanVideoWrapper完整教程&#xff1a;三步搭建AI视频生成工作站 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 还在为复杂的AI视频生成环境配置而烦恼吗&#xff1f;每次看到那些令人惊…...

${__RandomFromMultipleVars(rand_cat6,)}随机取值函数的使用

1、核心 从多个指定的变量&#xff08;或单个变量的多个值&#xff09;中随机抽取一个值 2、应用场景 ${__RandomFromMultipleVars(变量名1,变量名2,变量名3,...,输出变量名)} 结合之前的场景举例&#xff1a; 场景 1&#xff1a;若你在 CSV文件 中定义了 random_cat 变量…...

vLLM-v0.17.1效果展示:Qwen2-VL多模态模型vLLM适配初步成果

vLLM-v0.17.1效果展示&#xff1a;Qwen2-VL多模态模型vLLM适配初步成果 1. vLLM框架核心能力 vLLM是一个专为大型语言模型(LLM)设计的高性能推理和服务库&#xff0c;最初由加州大学伯克利分校的天空计算实验室开发&#xff0c;现已发展成为社区驱动的开源项目。最新发布的v0…...

用Zeek分析PCAP文件的完整流程:从基础命令到日志处理技巧

Zeek实战指南&#xff1a;从PCAP解析到威胁狩猎的全链路分析 1. 为什么选择Zeek进行流量分析&#xff1f; 在网络安全领域&#xff0c;流量分析工具如同侦探的放大镜&#xff0c;而Zeek&#xff08;原名Bro&#xff09;无疑是其中最强大的工具之一。不同于传统的IDS/IPS系统&am…...

从Prompt Engineering到Flow Engineering:基于AlphaCodium的AI代码生成实战

从Prompt Engineering到Flow Engineering&#xff1a;基于AlphaCodium的AI代码生成实战 最近在搞AI辅助开发&#xff0c;发现直接用大模型生成代码&#xff0c;效果就跟开盲盒似的。有时候写得挺好&#xff0c;有时候跑起来一堆bug&#xff0c;上下文一长它还容易“失忆”。为了…...