【网络】tcp_socket

tcp_socket

  • 一、tcp_server与udp_server一样的部分
  • 二、listen接口(监听)
  • 三、accept接收套接字
    • 1、为什么还要多一个套接字(明明已经有了个socket套接字文件了,为什么要多一个accept套接字文件?)
    • 2、底层拿到新连接并根据连接进行通信
    • 3、类比理解监听套接字和连接套接字的区别
  • 四、服务端提供服务(向客户端回消息)
  • 五、tcp_client客户端编写
    • 1、框架
    • 2、客户端卡退了,服务端怎么处理?(read返回值为0)
    • 3、一个有趣的现象--两个一样的客户端去连接客户端?(单进程服务)
    • 4、方法1:子进程关listensock,父进程关sockfd
    • 5、处理waitpid问题:孙子进程处理机制或者signal忽略信号
    • 6、方法2:多线程版本
    • 7、方法3:线程池版本
      • (1)线程池代码ThreadPool.hpp
      • (2)任务代码Task.hpp
      • (3)代码改进
      • (4)结果
  • 六、服务端翻译小程序
  • 七、进化版:出现错误的细节问题
    • 1、向一个已经关闭的文件描述符的文件中进行写入,读端已经关掉了,写端继续写,OS会把客户端进程杀掉
    • 2、重连
  • 八、在线翻译服务+重连
  • 九、地址复用
  • 十、守护进程介绍
  • 十一、tcp的通信原理


一、tcp_server与udp_server一样的部分

#pragma once#include <iostream>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>        
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h> 
#include "Log.hpp"Log lg;const int defaultfd = -1;
const std::string defaultip = "0.0.0.0";
const uint16_t defaultport = 8080;enum
{SocketERR=2,BINDERR=3
};class TcpServer
{
public:TcpServer(const uint16_t& port = defaultport, const std::string& ip = defaultip): _socketfd(defaultfd), _port(port), _ip(ip){}void InitServer(){_socketfd = socket(AF_INET, SOCK_STREAM, 0);if (_socketfd < 0){lg(Fatal, "create socket err, errno: %d, errst: %s", errno, strerror(errno));exit(SocketERR);}lg(Info, "create socket successful, sockfd:%d", _socketfd);struct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);inet_aton(_ip.c_str(), &(local.sin_addr));int n = bind(_socketfd, (struct sockaddr*)&local, sizeof(local));if (n < 0){lg(Fatal, "bind socket err, errno: %d, errst: %s", errno, strerror(errno));exit(BINDERR);}lg(Info, "bind sucessful");// 监听套接字  -- 因为tcp是要等待别人来连接的,所以要有个监听套接字进行监听等待别人来连接}void RunServer(){}~TcpServer(){}
private:int _socketfd;uint16_t _port;std::string _ip;
};

这里我们用inet_aton将本地序列转化成为网络序列。
在这里插入图片描述

二、listen接口(监听)

在这里插入图片描述

启动服务器,状态是listen:
在这里插入图片描述

三、accept接收套接字

在这里插入图片描述

1、为什么还要多一个套接字(明明已经有了个socket套接字文件了,为什么要多一个accept套接字文件?)

在这里插入图片描述
各司其职呗~~_socketfd是接客用的,面对随时来的新连接先接客到底层去,而accept的返回值才真正是服务的套接字,也就是I/O端口进行服务的,从底层拿出来进行服务!所以_socketfd只有一个,而accept返回值却有多个!(一个接客,多个服务员)
在这里插入图片描述

修改一下socket套接字为listen套接字:
在这里插入图片描述
在这里插入图片描述

2、底层拿到新连接并根据连接进行通信

在这里插入图片描述

在这里插入图片描述

3、类比理解监听套接字和连接套接字的区别

相当于我们去一家饭店,监听套接字是外面迎客的人,把人都迎进来,里面肯定有服务员吧,服务员就是连接套接字,服务员去服务,迎客的人去迎客。我们目前实现的是迎客连接一条龙,也就是来一群人,一个个迎客,再进来一个个服务,太慢了,所以我们的目标是实现迎客和服务两条线,来了人和迎客互不耽误,两者并发式的运行,就需要我们用多线程版本,但是会出现很多问题我们在下面一一进行讲解。

四、服务端提供服务(向客户端回消息)

那我们就写一个Server函数进行封装来将服务端进行提供服务!我们传参传accept从底层拿到的套接字和拿到的套接字的ip地址和port,我们找到ip地址用的是inet_ntop函数接口。
在这里插入图片描述
在这里插入图片描述

小问题:我上来通信的字符串和数字等难道到网络中不考虑大小端问题?我地址需要转大端,难道通信的字符串不用转吗?答案是肯定要转的,但是它网络里面自动帮忙转了。

在这里插入图片描述

我们用简单的Server函数中的代码为接收到消息,拼接一下再返回给服务器:
在这里插入图片描述
在这里插入图片描述

五、tcp_client客户端编写

1、框架

#include <iostream>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>        
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>void Usage(const std::string& proc)
{std::cout << "\n\rUsages: " << proc << "serverip serverport\n" << std::endl;
}// ./tcpclient serverip serverport
int main(int argc, char* argv[])
{if (argc != 3){Usage(argv[0]);exit(1);}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);int socketfd = socket(AF_INET, SOCK_STREAM, 0);if (socketfd < 0){std::cerr << "socket create error " << std::endl; return 1;}struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);inet_pton(AF_INET, serverip.c_str(), &(server.sin_addr));// tcp客户端要绑定,不需要显示绑定,os随机分配// 向网络服务器请求连接,客户端发起connect的时候,进行自动随机绑定int n = connect(socketfd, (struct sockaddr*)&server, sizeof(server));if (n < 0){std::cerr << "connect err " << std::endl;return 2;}// 连接成功std::string message;while (true){std::cout << "Please Enter@ ";std::getline(std::cin, message);char inbuffer[4096];write(socketfd, message.c_str(), message.size()); // 写进socketfdint n = read(socketfd, inbuffer, sizeof(inbuffer)); // 从socketfd读入inbufferif (n <= 0){std::cerr << "read err " << std::endl;return 3;}inbuffer[n] = 0;std::cout << inbuffer << std::endl;}close(socketfd);return 0;
}

在这里插入图片描述

2、客户端卡退了,服务端怎么处理?(read返回值为0)

客户端卡退了,服务端怎么办?
服务端保存好消息,其余不管,也就是我们的服务器read的返回值为0,也就是从底层拿到的连接的文件描述符值为0的时候,表示客户端退出。
在这里插入图片描述
在这里插入图片描述

3、一个有趣的现象–两个一样的客户端去连接客户端?(单进程服务)

在这里插入图片描述
理由是单进程版,得等一个进程搞好退出后才能实现另一个进程的使用。

4、方法1:子进程关listensock,父进程关sockfd

因为子进程会有很多没必要的listensock套接字,父进程会有很多没必要的sockfd套接字,子进程是进行监听,父进程是进行连接,其套接字本质不一样,子进程负责监听,父进程负责连接,所以把这些没必要的套接字都关了。
在这里插入图片描述
但这种情况父进程用waitpid还是有很大问题,因为父进程得等子进程退出!所以跟单进程没什么区别了,下面我们介绍怎么解决这个问题:

5、处理waitpid问题:孙子进程处理机制或者signal忽略信号

在这里插入图片描述

因为父进程等待子进程是阻塞的方式,导致的使父进程要一直等待子进程退出,子进程退出需要一定的时间,并且连的子进程多了,子进程就会一直运行,等待一个运行后再等下一个运行,时间太久了,所以我们使用一下子进程创建孙子进程的方法,子进程创建完立马退出,告诉父进程我退出了,父进程就能够执行下一步操作,而孙子进程去跑服务,并且孙子进程给操作系统进行托孤,孙子进程不受爷爷进程控制,并发的去跑进程。

但上面这个方法还是有很大的问题的,因为子进程的创建代价太大了,要有进程地址空间等很多需要创建的东西,很麻烦,所以我们用下面的这种方法:

6、方法2:多线程版本

在这里插入图片描述

在这里插入图片描述
上面的做法仍然有不合理之处,就是假如说是几亿个用户连接,那岂不是要几亿个线程,所以我们用线程池版本来解决!

7、方法3:线程池版本

(1)线程池代码ThreadPool.hpp

#pragma once#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <pthread.h>
#include <unistd.h>struct ThreadInfo
{pthread_t tid;std::string name;
};static const int defalutnum = 5;template <class T>
class ThreadPool
{
public:void Lock(){pthread_mutex_lock(&mutex_);}void Unlock(){pthread_mutex_unlock(&mutex_);}void Wakeup(){pthread_cond_signal(&cond_);}void ThreadSleep(){pthread_cond_wait(&cond_, &mutex_);}bool IsQueueEmpty(){return tasks_.empty();}std::string GetThreadName(pthread_t tid){for (const auto &ti : threads_){if (ti.tid == tid)return ti.name;}return "None";}public:static void *HandlerTask(void *args){ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);std::string name = tp->GetThreadName(pthread_self());while (true){tp->Lock();while (tp->IsQueueEmpty()){tp->ThreadSleep();}T t = tp->Pop();tp->Unlock();t();}}void Start(){int num = threads_.size();for (int i = 0; i < num; i++){threads_[i].name = "thread-" + std::to_string(i + 1);pthread_create(&(threads_[i].tid), nullptr, HandlerTask, this);}}T Pop(){T t = tasks_.front();tasks_.pop();return t;}void Push(const T &t){Lock();tasks_.push(t);Wakeup();Unlock();}static ThreadPool<T> *GetInstance(){if (nullptr == tp_) // ???{pthread_mutex_lock(&lock_);if (nullptr == tp_){std::cout << "log: singleton create done first!" << std::endl;tp_ = new ThreadPool<T>();}pthread_mutex_unlock(&lock_);}return tp_;}private:ThreadPool(int num = defalutnum) : threads_(num){pthread_mutex_init(&mutex_, nullptr);pthread_cond_init(&cond_, nullptr);}~ThreadPool(){pthread_mutex_destroy(&mutex_);pthread_cond_destroy(&cond_);}ThreadPool(const ThreadPool<T> &) = delete;const ThreadPool<T> &operator=(const ThreadPool<T> &) = delete; // a=b=c
private:std::vector<ThreadInfo> threads_;std::queue<T> tasks_;pthread_mutex_t mutex_;pthread_cond_t cond_;static ThreadPool<T> *tp_;static pthread_mutex_t lock_;
};template <class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr;template <class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;

(2)任务代码Task.hpp

#pragma once
#include <iostream>
#include <string>
#include "Log.hpp"
extern Log lg;class Task
{
public:Task(int sockfd, const std::string &ipstr, const uint16_t &clientport): _sockfd(sockfd), _clientip(ipstr), _clientport(clientport){}void run(){char buffer[4096];// 因为是面向字节流的,所以读网络跟读文件一样简单// 先读到bufferssize_t n = read(_sockfd, buffer, sizeof(buffer)); // 从套接字信息中读取消息存到buffer中if (n < 0){lg(Warning, "read err, readip:%s, readport:%d\n", _clientip.c_str(), _clientport);}else if (n == 0) // 客户端退出{lg(Info, "%s:%d quit, server close fd:%d", _clientip.c_str(), _clientport, _sockfd);}else{buffer[n] = 0;std::cout << "client say# " << buffer << std::endl;std::string echo_string = "tcpserver echo@ ";echo_string += buffer;// 再写入write(_sockfd, echo_string.c_str(), echo_string.size()); // 处理完的消息写回sockfd文件}close(_sockfd);}void operator()(){run();}private:int _sockfd;std::string _clientip;uint16_t _clientport;
};

(3)代码改进

void RunServer(){ThreadPool<Task>::GetInstance()->Start(); // 开启线程池的单例模式// signal(SIGCHLD, SIG_IGN); // 信号忽略lg(Info, "tcp_server is running...");while (true){struct sockaddr_in client;socklen_t len = sizeof(client);// 1.获取新连接int sockfd = accept(_listensocketfd, (struct sockaddr*)&client, &len);if (sockfd < 0){lg(Warning, "accept err, errno: %d, errst: %s", errno, strerror(errno));continue;}uint16_t clientport = ntohs(client.sin_port);char ipstr[32]; // 自定义的缓冲区inet_ntop(AF_INET, &(client.sin_addr), ipstr, sizeof(ipstr));// 2.根据新连接来通信lg(Info, "get a new link, sockfd:%d, clentip:%s, clientport:%d", sockfd, ipstr, clientport);// 3.4 线程池版本Task t(sockfd, ipstr, clientport);ThreadPool<Task>::GetInstance()->Push(t);}}

(4)结果

发送一则消息则退出线程。
在这里插入图片描述

六、服务端翻译小程序

Init.hpp:

#pragma once 
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include "Log.hpp"extern Log lg;const std::string dicname = "./dict.txt";
const std::string sep = ":";static bool Split(std::string &line, std::string* part1, std::string* part2) // line输入性参数 part1/2都是输出型参数
{auto pos = line.find(sep);if (pos == std::string::npos){return false;}*part1 = line.substr(0, pos);*part2 = line.substr(pos + 1);return true;
}class Init
{
public:Init(){std::ifstream in(dicname);if (!in.is_open()){lg(Fatal, "ifstream open %s error", dicname.c_str());exit(1);}std::string line;while (std::getline(in, line)){std::string part1, part2;Split(line, &part1, &part2);dict.insert({part1, part2});}in.close();}std::string Translation(const std::string& key){auto it = dict.find(key);if (it == dict.end()) return "Unkonw";else return it->second;}
private:std::unordered_map<std::string, std::string> dict;
};

Task.hpp:

#pragma once
#include <iostream>
#include <string>
#include "Log.hpp"
#include "Init.hpp"
extern Log lg;
Init init;
class Task
{
public:Task(int sockfd, const std::string &ipstr, const uint16_t &clientport): _sockfd(sockfd), _clientip(ipstr), _clientport(clientport){}void run(){char buffer[4096];// 因为是面向字节流的,所以读网络跟读文件一样简单// 先读到bufferssize_t n = read(_sockfd, buffer, sizeof(buffer)); // 从套接字信息中读取消息存到buffer中if (n < 0){lg(Warning, "read err, readip:%s, readport:%d\n", _clientip.c_str(), _clientport);}else if (n == 0) // 客户端退出{lg(Info, "%s:%d quit, server close fd:%d", _clientip.c_str(), _clientport, _sockfd);}else{buffer[n - 2] = 0;std::cout << "client key# " << buffer << std::endl;std::string echo_string = init.Translation(buffer);// 再写入write(_sockfd, echo_string.c_str(), echo_string.size()); // 处理完的消息写回sockfd文件}close(_sockfd);}void operator()(){run();}private:int _sockfd;std::string _clientip;uint16_t _clientport;
};

在这里插入图片描述

七、进化版:出现错误的细节问题

1、向一个已经关闭的文件描述符的文件中进行写入,读端已经关掉了,写端继续写,OS会把客户端进程杀掉

在这里插入图片描述

在这里插入图片描述

所以我们在write的时候都需要用返回值做一层判断,防止向已经关闭掉的文件描述符中写信息。要么就加信号忽略:
在这里插入图片描述

2、重连

tcpclient.cc:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

八、在线翻译服务+重连

我们先来这些词汇:
在这里插入图片描述
在这里插入图片描述

九、地址复用

在这里插入图片描述

十、守护进程介绍

守护进程

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

守护进程的启动bash:
在这里插入图片描述

带上日志文件(日志信息打印到当前路径下):
在这里插入图片描述

在这里插入图片描述

接口:默认00
在这里插入图片描述

十一、tcp的通信原理

在这里插入图片描述

tcp是全双工的:两个人吵架。
在这里插入图片描述

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

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

相关文章

从R-CNN到Faster-R-CNN的简单介绍

1、R-CNN RCNN算法4个步骤 1、一张图像生成1K~2K个候选区域(使用Selective Search方法) 2、对每个候选区域&#xff0c;使用深度网络提取特征 3、特征送入每一类的SVM分类器&#xff0c;判别是否属于该类 4、使用回归器精细修正候选框位置 R-CNN 缺陷 &#xff1a; 1.训练…

Java使用AsposePDF和AsposeWords进行表单填充

声明&#xff1a;本文为作者Huathy原创文章&#xff0c;禁止转载、爬取&#xff01;否则&#xff0c;本人将保留追究法律责任的权力&#xff01; 文章目录 AsposePDF填充表单adobe pdf表单准备引入依赖编写测试类 AsposeWord表单填充表单模板准备与生成效果引入依赖编码 参考文…

【C语言】链式队列的实现

队列基本概念 首先我们要了解什么是队列&#xff0c;队列里面包含什么。 队列是线性表的一种是一种先进先出&#xff08;First In Fi Out&#xff09;的数据结构。在需要排队的场景下有很强的应用性。有数组队列也有链式队列&#xff0c;数组实现的队列时间复杂度太大&#x…

【数据结构 | 哈希表】一文了解哈希表(散列表)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

虚拟局域网配置与分析-VLAN

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、相关知识 虚拟局域网&#xff08;Virtual Local Area Network&#xff0c;VLAN&#xff09;是一组逻辑上的设备和用户&#xff1b;不受物理位置的…

浅谈监听器之保存响应到文件

浅谈监听器之保存响应到文件 JMeter 提供了一个实用的监听器——“保存响应到文件”&#xff0c;该监听器能够自动将取样器的响应数据直接保存到指定的文件中&#xff0c;便于后续分析或存档。本文档旨在详细介绍如何配置和使用此监听器功能。 适用场景 ● 长时间运行的测试…

昇思25天学习打卡营第n天|本地安装mindspore之二|开始第一课的代码。以及对比xshell,MobaXterm

开始准备在本地的系统上跑例子了。从第一课开始吧。 1&#xff0c;下载代码 打开课程。 下载样例代码 https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.3/tutorials/zh_cn/beginner/mindspore_quick_start.py 2&#xff0c;在本地Linux上输入并运…

Python新手如何制作植物大战僵尸?这篇文章教会你!

引言 《植物大战僵尸》是一款非常受欢迎的塔防游戏&#xff0c;玩家需要种植各种植物来抵御僵尸的进攻。在这篇文章中&#xff0c;我们将使用Python编写一个简化版的植物大战僵尸游戏&#xff0c;以展示如何使用Python创建游戏。 游戏规则 玩家将种植不同类型的植物来防御僵尸…

好用的电脑录屏软件免费推荐,拥有这3款就能高效录屏!

电脑录屏软件已成为我们记录生活、分享知识的得力助手。但是&#xff0c;市面上琳琅满目的录屏软件令人眼花缭乱&#xff0c;如何才能选择到一款好用的电脑录屏软件免费神器呢&#xff1f;今天&#xff0c;就让我来为您揭晓这个秘密&#xff01; 首先&#xff0c;我们得明确一…

胖东来也要加入“打水仗”?瓶装水品牌又该如何出招

今年瓶装水行业的“战场”似乎格外热闹&#xff0c;比武汉的天气好像还要火热......从年头农夫山泉打出“纯净水”的牌&#xff0c;再到如今掀起价格内卷战&#xff0c;一箱12瓶的纯净水在某宝平台上仅售9.9元&#xff0c;平均下来每瓶单价不超一元&#xff0c;农夫山泉都出击了…

自动化网络爬虫:如何它成为提升数据收集效率的终极武器?

摘要 本文深入探讨了自动化网络爬虫技术如何彻底改变数据收集领域的游戏规则&#xff0c;揭示其作为提升工作效率的终极工具的奥秘。通过分析其工作原理、优势及实际应用案例&#xff0c;我们向读者展示了如何利用这一强大工具加速业务决策过程&#xff0c;同时保持数据收集的…

5G mmWave PAAM 开发平台

Avnet-Fujikura-AMD 5G 毫米波相控阵天线模块开发平台 Avnet 和 Fujikura 为毫米波频段创建了一个领先的 5G FR2 相控阵天线开发平台。该平台使开发人员能够使用 AMD Xilinx 的 Zynq UltraScale™ RFSoC Gen3 和 Fujikura 的 FutureAcess™ 相控阵天线模块 (PAAM) 快速创建和制…

算法日记day 18(二叉树的所有路径|左叶子之和)

一、二叉树的所有路径 题目&#xff1a; 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,5] 输出&#xff1a;["1->…

抖音矩阵管理系统解决方案:一站式服务

在当今社交媒体蓬勃发展的时代&#xff0c;抖音作为一款短视频平台&#xff0c;凭借其独特的魅力和庞大的用户群体&#xff0c;已成为众多企业、个人乃至网红达人展示自我、推广品牌的重要舞台。然而&#xff0c;随着抖音账号数量的不断增加&#xff0c;如何高效、专业地管理这…

系统编程--Linux下文件的“其他操作”函数

这里写目录标题 文件存储理论补充dentry、inode 文件其他操作stat函数作用函数原型代码&#xff08;以获取文件大小为例&#xff09;补充&#xff08;获取文件类型&#xff09; lstat函数作用函数原型代码补充&#xff08;获取文件权限&#xff09;总结 tipslink函数作用简介函…

前端页面:用户交互持续时间跟踪(duration)user-interaction-tracker

引言 在用户至上的时代&#xff0c;精准把握用户行为已成为产品优化的关键。本文将详细介绍 user-interaction-tracker 库&#xff0c;它提供了一种高效的解决方案&#xff0c;用于跟踪用户交互的持续时间&#xff0c;并提升项目埋点的效率。通过本文&#xff0c;你将了解到如…

使用水星Mecury人形机器人搭建VR遥操作控制平台!

VR遥操作机械臂是一种将虚拟现实技术与机械臂控制相结合的系统&#xff0c;使用户可以通过虚拟现实设备操控和交互实际的机械臂。这种技术可以应用于多个领域&#xff0c;包括远程操作、培训、危险环境中的工作等。 双臂人形机器人是一种模拟人体上半身结构&#xff0c;包括头部…

跨域浏览器解决前端跨域问题

1.问题背景 这是一种属于非主流的解决跨域的方案&#xff0c;但是也是可以正常使用而且比较简单的。如果需要使用主流的解决前端跨域方案&#xff0c;请参考这篇文章。 我这边其实是优先建议大家使用主流的跨域方案&#xff0c;如果主流的实在不行&#xff0c;那么就使用跨域…

多路复用IO、TCP并发模型

时分复用 CPU单核在同一时刻只能做一件事情&#xff0c;一种解决办法是对CPU进行时分复用(多个事件流将CPU切割成多个时间片&#xff0c;不同事件流的时间片交替进行)。在计算机系统中&#xff0c;我们用线程或者进程来表示一条执行流&#xff0c;通过不同的线程或进程在操作系…

通过POST请求往Elastic批量插入数据

文章目录 引言I 请求文档请求参数请求例子引言 调试工具:Apifox 需求: 向Elasticsearch中的’test_index’索引批量插入文档 情况认证: Basic Auth 在 Header 添加参数 Authorization,其值为在 Basic 之后拼接空格,以及经过 Base64 编码的 {{Username}}:{{Password}} 示…