网络套接字补充——UDP网络编程

五、UDP网络编程

​ 1.对于服务器使用智能指针维护生命周期;2.创建UDP套接字;3.绑定端口号,包括设置服务器端口号和IP地址,端口号一般是2字节使用uint16_t,而IP地址用户习惯使用点分十进制格式所以传入的是string类型,同时要保证网络字节序列;4.执行run;

​ UDP通信的socket是全双工的,允许被同时读写的;

5.1使用接口

5.1.1创建套接字
int socket(int domain, int type, int protocol);
//第一个参数为域/协议家族AF_UNIX, AF_LOCAL表示域间套接字,AF_INET ,AF_INET6表示网络套接字,AF_PACKET表示原始套接字,除了AF开头也可以PF开头;
//第二个参数表示socket的类型SOCK_STREAM表示流式套接字,SOCK_DGRAM表示数据包套接字;
//第三个参数如果只有一个协议则使用0;
//返回值是socket文件的文件描述符,打开的是网卡设备;

在这里插入图片描述

在这里插入图片描述

5.1.2进行绑定
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
struct sockaddr {sa_family_t sa_family;char        sa_data[14];
}
//第一个参数是创建好的套接字文件描述符;
//第二个参数是输入型参数,一个特定的结构需要使用其他结构进行强转;
//第三个参数特定类型的长度
//返回值成功为0失败为-1,错误码被设置;
#include <strings.h>
void bzero(void *s, size_t n);
#include <string.h>
void *memset(void *s, int c, size_t n);
//使用上述函数进行清空
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
struct in_addr
{in_addr_t s_addr;
};
typedef unsigned short int sa_family_t;
#define	__SOCKADDR_COMMON(sa_prefix) \sa_family_t sa_prefix##family
struct sockaddr_in
{__SOCKADDR_COMMON (sin_);in_port_t sin_port;			/* Port number.  */struct in_addr sin_addr;		/* Internet address.  *//* Pad to size of `struct sockaddr'.  */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];
};
sockaddr_in结构中,sin表示socket inet
sin_zero表示填充字段
sin_port表示端口号字段
sin_family表示使用的协议家族如AF_INET之类的
sin_addr表示的是IP地址结构
//local.sin_addr.s_addr = INADDR_ANY;//任意地址绑定
//字符串转整数接口
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);//将字符串转32位并且是网络序列的;
//整数转字符串
char *inet_ntoa(struct in_addr in);//将整数转为字符串并且将网络字节序转为主机字节序
5.1.3数据报的读取
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
//第四个参数默认使用0以阻塞方式
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
5.1.4数据报的发送
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

5.2补充知识

1.查看网络状态

netstat -nlupa
#查看网络状态,n表示能显示成数字的就都显示成数字,l表示listen u表示udp,p表示进程,a表示所有;

2.IP问题

​ 云服务器禁止直接绑定公网IP;配置较高的机器IP地址不唯一;只是绑定一个IP地址就会导致另一个IP地址的发往另一个IP地址的数据无法被接收;一般使用的是0,这样凡是发送给本主机的数据都要根据端口号向上交付,而不是先确定IP;即IP地址使用0表示的是任意地址绑定;

3.端口号问题

​ 云服务器端口号默认0-1023是不允许绑定的,是系统内定的端口号,一般由固定的应用层协议使用如,http-80,https-443,MySQL-3306,普通用户直接使用的一般是1024以后的端口号,端口号的范围是0-65535,可以在这个范围内使用;

​ 服务器需要绑定显式端口号但是客户端不需要显式绑定,操作系统会随机绑定;因为一个端口号只能被一个进程绑定,所以重复绑定同一个端口号会出错;防止出现这种冲突,就不允许用户显示绑定而是交给了操作系统,只要保证端口号的唯一性就可以,这样就不会导致不同软件的客户端出现绑定端口号冲突;一般服务器需要显示绑定端口号是因为一般是客户端先发送的请求,所以需要知道服务端的IP地址和端口号,且端口号不能发生变化必须是固定的,这样才能让客户端知道要发送的另一端进程是谁;

​ 系统会在客户端首次发送数据的时候进行端口号的绑定;客户端可以获取多个服务器的信息所以获取信息时要包含服务端的信息;

4.本地环回地址

​ 127.0.0.1是本地环回地址,通常来进行cs的测试;

5.3echo服务器实现

服务端

#include <sys/types.h>
#include <sys/socket.h>
#include "log.hpp"
#include <string>
#include <arpa/inet.h>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <functional>using func_t = std::function<std::string(const std::string &)>;
extern Log lg;const uint16_t defaultport = 8080;
const std::string defaultip = "0.0.0.0";
const int size = 1024;enum
{SOCKETERR = 1,BINDERR,
};class udpserver
{public:udpserver(const uint16_t &port = defaultport, const std::string &ip = defaultip) : ip_(ip), port_(port), isrunning_(false) {}~udpserver(){if (sockfd_ > 0){close(sockfd_);}}public:void init(){// 1.创建socketsockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){lg(Fatal, "socket create error, sockfd: %d", sockfd_);exit(SOCKETERR);}lg(Info, "socket create success, sockfd: %d", sockfd_);// 2.bindstruct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_);// local.sin_addr.s_addr = inet_addr(ip_.c_str());local.sin_addr.s_addr = INADDR_ANY;int n = bind(sockfd_, (sockaddr *)&local, sizeof(local));if (n < 0){lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));exit(BINDERR);}lg(Info, "bind success, errno: %d, strerror: %s", errno, strerror(errno));}void run(func_t func){isrunning_ = true;char buff[size];sockaddr_in client;socklen_t sz = sizeof(client);while (isrunning_){ssize_t n = recvfrom(sockfd_, buff, sizeof(buff) - 1, 0, (sockaddr *)&client, &sz);if (n < 0){lg(Warning, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));continue;}buff[n] = 0;// 处理数据std::string info = buff;std::string echo_string = func(info);sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0, (sockaddr *)&client, sz);}}private:int sockfd_;     // 网络文件描述符std::string ip_; // IP地址,1.将字符串风格转换为uint_t类型,2.转换成网络字节序列uint16_t port_;  // 端口号转换成网络字节序列bool isrunning_;
};--
void Usage(string proc)
{cout << "\n\rUsage: " << proc << " port[1024+]" << endl;
}string handler(const string &str)
{cout << str << endl;string ret = "server get a message: ";ret += str;return ret;
}int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);exit(0);}uint16_t port = stoi(argv[1]);unique_ptr<udpserver> svr(new udpserver(port, "127.0.0.1"));svr->init();svr->run(handler);return 0;
}

客户端

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "log.hpp"
extern Log lg;void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);return 0;}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){std::cerr << "socket error" << std::endl;exit(1);}sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = inet_addr(serverip.c_str());std::string message;char buff[1024];while (true){std::cout << "client say@ ";std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (sockaddr *)&server, sizeof(server));sockaddr_in temp;socklen_t len = sizeof(temp);ssize_t n = recvfrom(sockfd, buff, sizeof(buff) - 1, 0, (sockaddr *)&temp, &len);if (n > 0){buff[n] = 0;std::cout << buff << std::endl;}}close(sockfd);return 0;
}

5.4服务器实现执行指令

#include <stdio.h>
FILE *popen(const char *command, const char *type);
//是一个封装起来的管道和子进程执行命令的接口,会自动建立管道,让子进程执行命令并将子进程的执行结果通过管道返回给父进程;
//第一个参数是子进程要执行的命令,第二个参数是对打开文件的方式,读写;
//返回值是用来进行获取执行结果的;
int pclose(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
//读取一行,当读到EOF/空时返回nullptr;
bool safecheck(const string &cmd)
{int issafe = false;vector<string> keyword;keyword.push_back("rm");keyword.push_back("mv");keyword.push_back("kill");for (auto &e : keyword){auto pos = cmd.find(e);if (pos != string::npos){return issafe;}}issafe = true;return issafe;
}string execute(const string &cmd)
{if (!safecheck(cmd)){return "unsafe";}FILE *fp = popen(cmd.c_str(), "r");if (fp == nullptr){perror("popen error: ");return "error";}char buff[4096];string ret;while (true){char *res = fgets(buff, sizeof(buff), fp);if (res == nullptr){break;}ret += buff;}cout << "get a cmd: " << cmd << endl;pclose(fp);return ret;
}

​ Xshell的原理就是,远端执行了一个22服务,即ssh,客户端发送指令,服务端进行执行后返回结果;

在这里插入图片描述

5.5Windows和Linux通信

#include<iostream>
#include<WinSock2.h>//网络套接字接口#pragma comment(lib,"ws2_32.lib")//链接静态库using namespace std;int main()
{cout << "hello client" << endl;WSADATA wsd;//创建变量int n = WSAStartup(MAKEWORD(2, 2), &wsd);//初始化//通信过程WSACleanup();//释放变量return 0;
}
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
#include<iostream>
#include<WinSock2.h>//网络套接字接口
#include<string>#pragma comment(lib,"ws2_32.lib")//链接静态库using namespace std;
const uint16_t serverport = 8080;
const string serverip = "60.205.138.126";
int main()
{cout << "hello client" << endl;WSADATA wsd;int n = WSAStartup(MAKEWORD(2, 2), &wsd);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "socket error" << endl;}sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = inet_addr(serverip.c_str());std::string message;char buff[1024];while (true){std::cout << "client say@ ";std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (sockaddr*)&server, sizeof(server));sockaddr_in temp;int len = sizeof(temp);int n = recvfrom(sockfd, buff, sizeof(buff) - 1, 0, (sockaddr*)&temp, &len);if (n > 0){buff[n] = 0;std::cout << buff << std::endl;}}closesocket(sockfd);WSACleanup();return 0;
}

5.6制作一个聊天室,获取用户IP

​ 1.recvfrom不仅可以获取收到的信息,还可以获取发送方的sockaddr_in信息,用来知道发送方的信息;2.将处理数据和产生数据用回调函数的方式来进行软件分层,也可以类内创建一个函数处理;3.客户端使用getline会阻塞住,并不能获取其他客户端发来的消息,所以需要使用多路复用将接口设置为非阻塞才能解决此问题;4.可以将客户端多线程化解决;

vs2019下客户端

#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
#include <iostream>
#include <WinSock2.h> //网络套接字接口
#include <string>
#include <thread>#pragma comment(lib, "ws2_32.lib") // 链接静态库
using namespace std;
const uint16_t serverport = 8080;
const string serverip = "60.205.138.126";void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}void recvr(int sockfd)
{char buff[1024];while (true){sockaddr_in temp;int len = sizeof(temp);int n = recvfrom(sockfd, buff, sizeof(buff) - 1, 0, (sockaddr*)&temp, &len);if (n > 0){buff[n] = 0;std::cout << buff << std::endl;}}
}void sendr(int sockfd, sockaddr_in server)
{std::string message;while (true){std::cout << "vs2019 say@ ";std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (sockaddr*)&server, sizeof(server));}
}int main(int argc, char* argv[])
{WSADATA wsd;//创建变量int n = WSAStartup(MAKEWORD(2, 2), &wsd);//初始化int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){std::cerr << "socket error" << std::endl;exit(1);}sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = inet_addr(serverip.c_str());thread r(recvr, sockfd);thread s(sendr, sockfd, server);r.join();s.join();closesocket(sockfd);WSACleanup();return 0;
}

g++下客户端

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include "log.hpp"
extern Log lg;void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}struct threadinfo
{threadinfo(int sockfd, const sockaddr_in &server) : sockfd_(sockfd){server_.sin_family = server.sin_family;server_.sin_port = server.sin_port;server_.sin_addr.s_addr = server.sin_addr.s_addr;}int sockfd_;sockaddr_in server_;
};void *recv(void *args)
{threadinfo *td = static_cast<threadinfo *>(args);char buff[1024];while (true){sockaddr_in temp;socklen_t len = sizeof(temp);ssize_t n = recvfrom(td->sockfd_, buff, sizeof(buff) - 1, 0, (sockaddr *)&temp, &len);if (n > 0){buff[n] = 0;std::cout << buff << std::endl;}}
}void *send(void *args)
{threadinfo *td = static_cast<threadinfo *>(args);std::string message;while (true){std::cout << "tencent say@ ";std::getline(std::cin, message);sendto(td->sockfd_, message.c_str(), message.size(), 0, (sockaddr *)&td->server_, sizeof(td->server_));}
}int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);return 0;}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){std::cerr << "socket error" << std::endl;exit(1);}sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = inet_addr(serverip.c_str());pthread_t rtid, stid;threadinfo *td = new threadinfo(sockfd, server);pthread_create(&rtid, nullptr, recv, (void *)td);pthread_create(&stid, nullptr, send, (void *)td);pthread_join(rtid, nullptr);pthread_join(stid, nullptr);close(sockfd);return 0;
}

效果展示

在这里插入图片描述

5.7使用终端模拟图形化界面将输入和输出分开

/dev/pts
#存放的是打开的终端文件,可以直接输出重定向到终端文件里面
echo "hello">/dev/pts/0

在这里插入图片描述

在这里插入图片描述

const std::string terminal = "/dev/pts/2";void openTerminal()
{int fd = open(terminal.c_str(), O_WRONLY);dup2(fd, 2);
}
./client 60.205.138.126 8080 2>/dev/pts/2
#也可以实现重定向
Linux中两个机器之间传输文件
scp client dyh@82.156.23.226:/home/dyh
#将本机文件发送到另一端Linux机器
scp dyh@60.205.138.126:/home/dyh/11/client .
#从其他Linux机器获取文件

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

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

相关文章

Stream流的详细说明

什么是stream流 Stream流是指一种数据处理的概念&#xff0c;它可以将数据以连续的方式传输&#xff0c;而不用等待整个数据集全部加载完成。在计算机编程中&#xff0c;Stream流通常用于处理大数据集或实时数据流。 Stream流可以分为输入流和输出流&#xff0c;输入流用于从数…

应用开发平台集成表单设计器系列之6——表单构造器集成实战

背景 平台需要实现自定义表单功能&#xff0c;作为低代码开发的一部分&#xff0c;通过技术预研和技术选型&#xff0c;选择form-create和form-create-designer这两个组件进行集成作为实现方案。通过深入了解和技术验证&#xff0c;确认了组件的功能能满足需求&#xff0c;具备…

Android 手机恢复出厂设置后可以恢复数据吗?

将 Android 手机恢复出厂设置是否会永久删除所有内容&#xff0c;或者您​​仍然可以检索部分数据吗&#xff1f; 如果您无法再使用 Android 手机&#xff0c;唯一的解决方案可能是将其恢复出厂设置。恢复出厂设置&#xff08;也称为硬重置&#xff09;会删除设备中的所有设置…

Qt案例 调用WINDOWS API中的SETUPAPI.H库获取设备管理器中设备的详细信息中的属性值(二)

使用Qt调用windows api中的setupapi.h库中的SetupDiGetDeviceRegistryProperty和SetupDiGetDeviceProperty函数获取设备管理器中的设备详细信息中的属性值&#xff0c;包括设备实例路径&#xff0c;硬件id,驱动inf名称&#xff0c;驱动版本&#xff0c;显示名称&#xff0c;类名…

数据结构——二叉树——堆

前言&#xff1a; 在前面我们已经学习了数据结构的基础操作&#xff1a;顺序表和链表及其相关内容&#xff0c;今天我们来学一点有些难度的知识——数据结构中的二叉树&#xff0c;今天我们先来学习二叉树中堆的知识&#xff0c;这部分内容还是非常有意思的&#xff0c;下面我们…

虚拟机Linux(centos)安装python3.8(超详细)

一、Python下载 下载地址&#xff1a;https://www.python.org/downloads/source/ 输入下面网址即可直接下载&#xff1a; python3.8&#xff1a;https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz python3.6&#xff1a;https://www.python.org/ftp/python/3.6.5/…

微信小程序(黑马优购:登录)

1.点击结算进行条件判断 user.js //数据 state: () >({ // address: {} address: JSON.parse(uni.getStorageSync(address) || {}), token: }), my-settle.vue computed: { ...mapGetters(m_cart,[checkedCount,total,checkedGoodsAmount]), …

IP种子是什么?理解和应用

在网络世界中&#xff0c;IP种子是一个广泛应用于文件共享和网络下载领域的概念。它是一种特殊的标识符&#xff0c;用于识别和连接到基于对等网络&#xff08;P2P&#xff09;协议的文件共享网络中的用户或节点。本文将深入探讨IP种子的含义、作用以及其在网络中的应用。 IP地…

【Linux】TCP网络套接字编程+守护进程

文章目录 日志类&#xff08;完成TCP/UDP套接字常见连接过程中的日志打印&#xff09;单进程版本的服务器客户端通信多进程版本和多线程版本守护进程化的多线程服务器 日志类&#xff08;完成TCP/UDP套接字常见连接过程中的日志打印&#xff09; 为了让我们的代码更规范化&…

瑞_23种设计模式_观察者模式

文章目录 1 观察者模式&#xff08;Observer Pattern&#xff09;1.1 介绍1.2 概述1.3 观察者模式的结构1.4 观察者模式的优缺点1.5 观察者模式的使用场景 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 JDK中提供的观察者模式实现 ★4.1 Observable类4.2 Obse…

Day63-LVS四层负载均衡及结合Nginx7层负载均衡实践

Day63-LVS四层负载均衡及结合Nginx7层负载均衡实践 1. LVS&#xff08;Linux Virtual Server&#xff09;介绍2. IPVS&#xff08;LVS&#xff09;发展史3. IPVS软件工作层次图4. LVS技术点小结5. LVS的4模式原理讲解5.1 NAT(Network AddressTranslation)&#xff0c;中文网络地…

《Retrieval-Augmented Generation for Large Language Models: A Survey》 AI 解读

论文链接&#xff1a;Retrieval-Augmented Generation for Large Language Models: A Survey 论文标题&#xff1a;《Retrieval-Augmented Generation for Large Language Models: A Survey》 一译中文版地址&#xff1a; https://yiyibooks.cn/arxiv/2312.10997v5/index.htm…

PI案例分享--2000A核心电源网络的设计、仿真与验证

目录 摘要 0 引言 1 为什么需要 2000A 的数字电子产品? 2 2000A 的供电电源设计 2.1 "MPM3698 2*MPM3699"的 MPS扩展电源架构 2.2 使用恒定导通时间(COT)模式输出核心电压的原因 2.3 模块化 VRM 的优势 2.4 用步进负载验证2000A的设计难点 2.4.1 电源网络 …

qtcreator的信号槽链接

在ui文件中简单创建一个信号槽连接并保存可以在ui_mainwindow.h下 class Ui_MainWindow 类 void setupUi(QMainWindow *MainWindow)函数 找到对应代码 QObject::connect(pushButton, SIGNAL(clicked()), MainWindow, SLOT(close())); 下拉&#xff0c;由于 class MainWind…

《权力》为什么只为某些人所拥有 - 三余书屋 3ysw.net

权力&#xff1a;为什么只为某些人所拥有 大家好&#xff0c;今天我们解读的书名是《权力》&#xff0c;副标题是“为什么只为某些人所拥有”。该书深入探讨了职场中的权力议题&#xff0c;强调获得权力是关键的职场技能之一。在激烈的职场竞争中&#xff0c;缺乏这一技能将使…

C#(winform) 调用MATLAB函数

测试环境 VisualStudio2022 / .NET Framework 4.7.2 Matlab2021b 参考&#xff1a;C# Matlab 相互调用 Matlab 1、编写Matlab函数 可以没有任何参数单纯定义matlab处理的函数&#xff0c;输出的数据都存在TXT中用以后期读取数据 function [result,m,n] TEST(list) % 计算…

Python 后端 Flask 使用 Flask-SocketIO、前端 Vue3 实现长连接 Websocket 通信详细教程(更新中)

Flask 安装 Flask-Socketio Flask-SocketIO 第三方库使 Flask 应用程序可以实现客户端和服务器之间的低延迟双向通信。客户端应用程序可以使用 Javascript、Python、C、Java 和 Swift 中的任何 SocketIO 客户端库或任何其他兼容客户端来建立与服务器的永久连接。 Flask-Socke…

逐步学习Go-Select多路复用

概述 这里又有多路复用&#xff0c;但是Go中的这个多路复用不同于网络中的多路复用。在Go里&#xff0c;select用于同时等待多个通信操作&#xff08;即多个channel的发送或接收操作&#xff09;。Go中的channel可以参考我的文章&#xff1a;逐步学习Go-并发通道chan(channel)…

使用 Yoda 和 ClickHouse 进行实时欺诈检测

背景 Instacart 是北美领先的在线杂货公司,拥有数百万活跃的客户和购物者。在其平台上打击欺诈和滥用行为不仅对于维护一个值得信赖和安全的环境至关重要,也对保持Instacart的财务健康至关重要。在这篇文章中,将介绍了一个欺诈平台——Yoda,解释了为什么我们选择ClickHous…

【踩坑】荣耀系统Android8.0 system目录Read-only file system

本来以为直接把Charles证书改成系统证书格式&#xff0c;然后通过mt管理器root之后移动到系统证书目录就行了&#xff0c;结果访问baidu仍然显示网络错误&#xff0c;折腾一晚上。后来直接安装为用户证书&#xff0c;与系统证书冲突。 手机型号&#xff1a;荣耀v10 EMUI&…