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

【网络】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是全双工的:两个人吵架。
在这里插入图片描述

相关文章:

【网络】tcp_socket

tcp_socket 一、tcp_server与udp_server一样的部分二、listen接口&#xff08;监听&#xff09;三、accept接收套接字1、为什么还要多一个套接字&#xff08;明明已经有了个socket套接字文件了&#xff0c;为什么要多一个accept套接字文件&#xff1f;&#xff09;2、底层拿到新…...

Live555源码阅读笔记:哈希表的实现

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

vue3创建vite项目

一、创建vue3 vite项目&#xff1a; 命令行创建&#xff1a;npm create vitelatest vue3-tdly-demo -- --template vue (1)先进入项目文件夹&#xff0c;cd vue3-tdly-demo (2)之后执行&#xff0c; npm install (3)最后运行&#xff0c;npm run dev 将main.js文件内容改成…...

Maven概述

目录 1.Maven简介 2.Maven开发环境搭建 2.1下载Maven服务器 2.2安装&#xff0c;配置Maven 1.配置本地仓库地址 2.配置阿里云镜像地址 2.3在idea中配置maven 2.4在idea中创建maven项目 3.pom.xml配置 1.项目基本信息 2.依赖信息 3.构建信息 4.Maven命令 5.打包Jav…...

Easyu中datagrid点击时获取所在行的数据

问题 双击单元格时&#xff0c;获取该行的记录内容 $(#list).datagrid({method: post,url: user/list,queryParams:{sex : "f",age : "18~25"},fitColumns: true,pageList: [ 5, 10, 15, 20 ],singleSelect: false,pagination: true,fit: true,rownumber…...

java项目中添加SDK项目作为依赖使用(无需上传Maven)

需求&#xff1a; 当需要多次调用某个函数或算法时&#xff0c;不想每次调用接口都自己编写&#xff0c;可以将该项目打包&#xff0c;以添加依赖的方式实现调用 适用于&#xff1a; 无需上线的项目&#xff0c;仅公司或团队内部使用的项目 操作步骤&#xff1a; 以下面这…...

区块链和数据要素融合的价值及应用

一、数据要素面临的关键障碍 在构建数据要素基石的过程中&#xff0c;首要任务是明确并解决产权架构的难题&#xff0c;特别是使用权的确立与流转机制的顺畅&#xff0c;此乃数字经济蓬勃发展的命脉所在。一个高效的数据流转体系对于激发数据潜能、加速经济发展及优化数据资源…...

以太坊的可扩展性危机:探索执行层的瓶颈

导读&#xff1a;以太坊执行层承担着交易处理、智能合约执行以及保持一致和安全状态的维护等工作。Fuel Labs 撰文解析了以太坊执行层的工作原理&#xff0c;及其在可扩展性方面的发展瓶颈和影响。 Fuel Labs: 执行是指在区块链上执行交易和执行状态更改所需的计算。此计算通常…...

静态解析activiti文本,不入库操作流程

说明&#xff1a; activiti本身状态存库&#xff0c;导致效率太低&#xff0c;把中间状态封装成一个载荷类&#xff0c;返回给上游&#xff0c;下次请求时给带着载荷类即可。 1.pom依赖 <dependency><groupId>net.sf.json-lib</groupId><artifactId>js…...

100个python的基本语法知识【上】

0. 变量和赋值&#xff1a; x 5 name “John” 1. 数据类型&#xff1a; 整数&#xff08;int&#xff09; 浮点数&#xff08;float&#xff09; 字符串&#xff08;str&#xff09; 布尔值&#xff08;bool&#xff09; 2. 注释&#xff1a; # 这是单行注释 ""…...

Python从0到100(四十四):读取数据库数据

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…...

ZLMRTCClient配置说明与用法(含示例)

webRTC播放视频 后面在项目中会用到通过推拉播放视频流的技术&#xff0c;所以最近预研了一下webRTC 首先需要引入封装好的webRTC客户端的js文件ZLMRTCClient.js 下面是地址需要的自行下载 http://my.zsyou.top/2024/ZLMRTCClient.js 配置说明 new ZLMRTCClient.Endpoint…...

nginx代理服务配置,基于http协议-Linux(CentOS)

基于http协议的nginx代理服务 1. 打开 Nginx 虚拟机80端口配置文件2. 添加代理配置3. 重启nginx服务 nginx代理缓存配置 1. 打开 Nginx 虚拟机80端口配置文件 Nginx 的默认80端口虚拟机配置文件通常位于/etc/nginx/conf.d/default.conf。 vim /etc/nginx/conf.d/default.con…...

Photos框架 - 自定义媒体资源选择器(数据部分)

引言 在iOS开发中&#xff0c;系统已经为我们提供了多种便捷的媒体资源选择方式&#xff0c;如UIImagePickerController和PHPickerViewController。这些方式不仅使用方便、界面友好&#xff0c;而且我们完全不需要担心性能和稳定性问题&#xff0c;因为它们是由系统提供的&…...

Spring Boot + Spring Cloud 入门

运行配置 java -jar spring-boot-config-0.0.1-SNAPSHOT.jar --spring.profiles.activetest --my1.age32 --debugtrue "D:\Program Files\Redis\redis-server.exe" D:\Program Files\Redis\redis.windows.conf "D:\Program Files\Redis\redis-cli.exe" &q…...

怎么使用动态IP地址上网

如何设置动态IP地址上网&#xff1f; 设置动态IP地址上网的步骤如下&#xff1a; 一、了解动态IP地址 动态IP地址是由网络服务提供商&#xff08;ISP&#xff09;动态分配给用户的IP地址&#xff0c;它会根据用户的需求和网络情况实时改变。相比于静态IP地址&#xff0c;动态…...

【源码+文档+调试讲解】智慧物流小程序的设计与实现

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对高校教师成果信息管理混乱&#xff0c;出错率高&#xff0c;信息安全…...

QT:控件圆角设置、固定窗口大小

实现控件圆角度设置//使用的是setStyleSheet方法 //改变的控件是QTextEdit&#xff0c;如果你想改变其他控件&#xff0c;将QTextEdit进行更换 this->setStyleSheet("QTextEdit{background-color:#FFFFFF;border-top-left-radius:15px;border-top-right-radius:15px;bo…...

【JavaScript】深入理解 `let`、`var` 和 `const`

文章目录 一、var 的声明与特点二、let 的声明与特点三、const 的声明与特点四、let、var 和 const 的对比五、实战示例六、最佳实践 在 JavaScript 中&#xff0c;变量声明是编程的基础&#xff0c;而 let、var 和 const 是三种常用的变量声明方式。本文将详细介绍这三种变量声…...

云监控(华为) | 实训学习day7(10)

水一篇。。。。。。。。。。。。。 强迫症打卡必须要满 企拓 今天没有将东西 2024/7/22 规划学习路线对于进入AI行业至关重要。以下是一个详细的学习路线规划&#xff0c;旨在帮助你从零基础到成为一名合格的AI或大数据分析师&#xff1a; 第一阶段&#xff1a;基础知识建设…...

JS_plus.key.addEventListener监听键盘按键

官方文档&#xff1a;https://www.html5plus.org/doc/zh_cn/key.html 监听事件 plus.key.addEventListener(keydown, e > {console.log("keydown: "e.keyCode) }) plus.key.addEventListener(keyup, e > {console.log("keyup: "e.keyCode) })移除事…...

对话系统(Chat)与自主代理(Agent)对撞

随着生成式AI技术的不断进步&#xff0c;关于其未来发展方向的讨论也愈发激烈。究竟生成式AI的未来是在对话系统&#xff08;Chat&#xff09;中展现智慧&#xff0c;还是在自主代理&#xff08;Agent&#xff09;中体现能力&#xff1f;这一问题引发了广泛的讨论和探索。 首先…...

sql server 连接报错error 40

做个简单的记录,造成40 的原因有很多,你的错误并不一定就是我遇到的这种情况. 错误描述: 首先我在使用ssms 工具连接的时候是可以正常连接的,也能对数据库进行操作. 在使用 ef core 连接 Sql Server 时报错: Microsoft.Data.SqlClient.SqlException (0x80131904): A network-r…...

邮件安全篇:如何防止邮件泄密?

本文主要讨论组织内部用户违反保密规定通过邮件泄密的场景。其他场景导致邮箱泄密的问题&#xff08;如账号被盗、邮件系统存在安全漏洞等&#xff09;不在本文的讨论范围。本文主要从邮件系架构设计、邮件数据防泄漏系统、建立健全规章制度、安全意识培训等方面分别探讨。 1. …...

MySQL查询优化:提升数据库性能的策略

在数据库管理和应用中&#xff0c;优化查询是提高MySQL数据库性能的关键环节。随着数据量的不断增长&#xff0c;如何高效地检索和处理数据成为了一个重要的挑战。本文将介绍一系列优化MySQL查询的策略&#xff0c;帮助开发者和管理员提升数据库的性能。 案例1: 使用索引优化查…...

vue-快速入门

Vue 前端体系、前后端分离 1、概述 1.1、简介 Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;可以高效地开发用户界面。…...

【网络流】——初识(最大流)

网络流-最大流 基础信息引入一些概念基本性质 最大流定义 Ford–Fulkerson 增广Edmons−Karp算法Dinic 算法参考文献 基础信息 引入 假定现在有一个无限放水的自来水厂和一个无限收水的小区&#xff0c;他们之间有多条水管和一些节点构成。 每一条水管有三个属性&#xff1a…...

【STM32嵌入式系统设计与开发---拓展】——1_10矩阵按键

这里写目录标题 1、矩阵按键2、代码片段分析 1、矩阵按键 通过将4x4矩阵按键的每一行依次设为低电平&#xff0c;同时保持其它行为高电平&#xff0c;然后读取所有列的电平状态&#xff0c;可以检测到哪个按键被按下。如果某列变为低电平&#xff0c;说明对应行和列的按键被按下…...

长期更新方法库推荐pmq-ui

# pmq-ui pmq-ui 好用方法库ui库, 欢迎您的使用 ## 安装 1. 克隆项目库到本地&#xff1a; 2. 进入项目目录&#xff1a;cd pmq-ui 3. 安装依赖&#xff1a;npm install pmq-ui ## 使用 <!-- 1. 启动应用&#xff1a; 2. 访问 [http://localhost:3000](http://localhost:300…...

<数据集>抽烟识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;4860张 标注数量(xml文件个数)&#xff1a;4860 标注数量(txt文件个数)&#xff1a;4860 标注类别数&#xff1a;1 标注类别名称&#xff1a;[smoking] 使用标注工具&#xff1a;labelImg 标注规则&#xff1a;对…...

SQL Server 端口设置教程

引言 你好&#xff0c;我是悦创。 在配置 SQL Server 的过程中&#xff0c;设置正确的端口非常关键&#xff0c;因为它影响到客户端如何连接到 SQL Server 实例。默认情况下&#xff0c;SQL Server 使用 TCP 端口 1433&#xff0c;但在多实例服务器上或出于安全考虑&#xff…...

【React1】React概述、基本使用、脚手架、JSX、组件

文章目录 1. React基础1.1 React 概述1.1.1 什么是React1.1.2 React 的特点声明式基于组件学习一次,随处使用1.2 React 的基本使用1.2.1 React的安装1.2.2 React的使用1.2.3 React常用方法说明React.createElement()ReactDOM.render()1.3 React 脚手架的使用1.3.1 React 脚手架…...

k8s部署kafka集群

k8s部署kafka集群 kafka&#xff08;Kafka with KRaft&#xff09; mkdir -p ~/kafka-ymlkubectl create ns kafkacat > ~/kafka-yml/kafka.yml << EOF apiVersion: v1 kind: Service metadata:name: kafka-headlessnamespace: kafkalabels:app: kafka spec:type: C…...

(C++回溯01) 组合

77、组合 回溯题目三步走 1. 确定参数 2. 确定终止条件 3. for 循环横向遍历&#xff0c;递归纵向遍历 class Solution { public:vector<vector<int>> result;vector<int> path;void backtracking(int n, int k, int startIndex) {if(path.size() k) {…...

k8s学习笔记——安装istio的仪表盘之prometheus安装

接上一篇&#xff0c;继续安装istio的dashboard。 先到istio-1.22.0/samples/addons目录下&#xff0c;把yaml文件中的镜像仓库地址修改了&#xff0c;修改地址参考我之前写的CSDN里的镜像对照表。不然直接执行kubectl apply -f samples/addons这个命令后&#xff0c;依据会出…...

四、GD32 MCU 常见外设介绍 (7) 7.I2C 模块介绍

7.1.I2C 基础知识 I2C(Inter-Integrated Circuit)总线是一种由Philips公司开发的两线式串行总线&#xff0c;用于内部IC控制的具有多端控制能力的双线双向串行数据总线系统&#xff0c;能够用于替代标准的并行总线&#xff0c;连接各种集成 电路和功能模块。I2C器件能够减少电…...

Apollo 配置中心的部署与使用经验

前言 Apollo&#xff08;阿波罗&#xff09;是携程开源的分布式配置管理中心。 本文主要介绍其基于 Docker-Compose 的部署安装和一些使用的经验 特点 成熟&#xff0c;稳定支持管理多环境/多集群/多命名空间的配置配置修改发布实时&#xff08;1s&#xff09;通知到应用程序支…...

Perl中的设计模式革新:命令模式的实现与应用

Perl中的设计模式革新&#xff1a;命令模式的实现与应用 在面向对象编程中&#xff0c;设计模式是解决特定问题的成熟模板。命令模式作为行为设计模式之一&#xff0c;它将请求封装为对象&#xff0c;从而允许用户根据不同的请求对客户进行参数化。本文将深入探讨如何在Perl中…...

Java8-求两个集合取交集

在Java8中&#xff0c;求两个集合的交集可以使用不同的三种方式&#xff1a;传统的循环遍历、使用Stream API的filter操作和使用Stream API的Collection操作。 方法一&#xff1a;传统的循环遍历 首先&#xff0c;我们创建两个集合list1和list2&#xff0c;并给它们添加一些元…...

爬虫学习4:爬取王者荣耀技能信息

爬虫&#xff1a;爬取王者荣耀技能信息&#xff08;代码和代码流程&#xff09; 代码 # 王者荣耀英雄信息获取 import time from selenium import webdriver from selenium.webdriver.common.by import By if __name__ __main__:fp open("./honorKing.txt", "…...

在Ubuntu 14.04上安装和使用Memcache的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 随着您的网站的增长和流量的增加&#xff0c;最快显示压力的组件之一是后端数据库。如果您的数据库没有分布式和配置来处理高负载…...

PCDN技术如何降低运营成本?

PCDN技术通过以下几种方式降低运营商的运营成本: 1.利用用户设备作为缓存节点: PCDN技术将用户设备纳入内容分发网络&#xff0c;利用这些设备的闲置带宽和存储资源来缓存和分发内容。这种方式不需要运营商投入大量的高成本服务器和带宽资源&#xff0c;从而降低了硬件和带宽…...

服务器数据恢复—V7000存储硬盘故障脱机的数据恢复案例

服务器存储数据恢复环境&#xff1a; 某品牌P740小型机AIXSybaseV7000磁盘阵列柜&#xff0c;磁盘阵列柜中有12块SAS机械硬盘&#xff08;其中包括一块热备盘&#xff09;。 服务器存储故障&#xff1a; 磁盘阵列柜中有一块磁盘出现故障&#xff0c;运维人员用新硬盘替换掉故障…...

BSV区块链在人工智能时代的数字化转型中的角色

​​发表时间&#xff1a;2024年6月13日 企业数字化转型已有约30年的历史&#xff0c;而人工智能&#xff08;以下简称AI&#xff09;将这种转型提升到了一个全新的高度。这并不难理解&#xff0c;因为AI终于使企业能够发挥其潜力&#xff0c;实现更宏大的目标。然而&#xff0…...

android audio 相机按键音:(二)加载与修改

相机按键音资源&#xff0c;加载文件路径&#xff1a; frameworks/av/services/camera/libcameraservice/CameraService.cpp 按键音&#xff0c;加载函数&#xff1a; void CameraService::loadSoundLocked(sound_kind kind) { ATRACE_CALL(); LOG1("Cam…...

Linux grep技巧 提取log中的json数据

目录 一. 前提1.1 数据准备1.2 需求1.3 分析 二. 数据提取2.1 提取所有的json数据2.2 提取子项目的全部json数据2.3 提取指定项目的json数据 一. 前提 1.1 数据准备 545-1 2024/07/20 18:20:21 [ERROR] MPX001 eventControlleraupay transactionIdA545 {"event":&q…...

HDShredder 7 企业版案例分享: 依照国际权威标准,安全清除企业数据

HDShredder 7 企业版用户案例 天津鸿萌科贸发展有限公司是德国 Miray 公司 HDShredder 数据清除软件的授权代理商。近日&#xff0c;上海某网络科技有限公司采购 HDShredder 7 企业版x4&#xff0c;为公司数据存储资产的安全清除工作流程配备高效的执行工具。HDShredder 7 企业…...

centos系统使用mysqldump数据备份与恢复

文章目录 使用mysqldump备份数据库一、数据库备份1. 基础备份2. 额外选项(一般组合使用) 二、数据库恢复 使用mysqldump备份数据库 一、数据库备份 1. 基础备份 #备份单个数据库 mysqldump -u 用户名 -p 数据库名 > 备份文件.sql#备份多个数据库 mysqldump -u 用户名 -p …...

【element ui】input输入控件绑定粘贴事件,从 Excel 复制的数据粘贴到输入框(el-input)时自动转换为逗号分隔的数据

目录 1、需求2、实现思路:3、控件绑定粘贴事件事件修饰符说明: 4、代码实现&#x1f680;写在最后 1、需求 在 Vue 2 和 Element UI 中&#xff0c;要实现从 Excel 复制空格分隔的数据&#xff0c;并在粘贴到输入框&#xff08;el-input&#xff09;时自动转换为逗号分隔的数据…...

Chapter18 基于物理的渲染——Shader入门精要学习

Chapter18 基于物理的渲染 一、PBS理论和数学基础1.光是什么微表面模型 2.渲染方程3.精确光源4.双向反射分布函数 BRDF5.漫反射项&#xff08;Lambert 模型&#xff09;Lambertian BRDF为&#xff1a;Disney BRDF中漫反射项 6.高光反射项微面元理论BRDF的高光反射项①菲涅尔反射…...