【在Linux世界中追寻伟大的One Piece】Socket编程TCP(续)

目录

1 -> V2 -Echo Server多进程版本

2 -> V3 -Echo Server多线程版本

3 -> V3-1 -多线程远程命令执行

4 -> V4 -Echo Server线程池版本


1 -> V2 -Echo Server多进程版本

通过每个请求,创建子进程的方式来支持多连接。

InetAddr.hpp

#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

class InetAddr
{
public:
	InetAddr(struct sockaddr_in& addr) :_addr(addr)
	{
		_port = ntohs(_addr.sin_port);
		_ip = inet_ntoa(_addr.sin_addr);
	}

	std::string Ip() 
	{ 
		return _ip; 
	}

	uint16_t Port() 
	{ 
		return _port; 
	};

	std::string PrintDebug()
	{
		std::string info = _ip;
		info += ":";
		info += std::to_string(_port); // "127.0.0.1:4444"

		return info;
	}

	const struct sockaddr_in& GetAddr()
	{
		return _addr;
	}

	bool operator == (const InetAddr & addr)
	{
		//other code
		return this->_ip == addr._ip && this->_port == addr._port;
	}

	~InetAddr() {}

private:
	std::string _ip;
	uint16_t _port;
	struct sockaddr_in _addr;
};

TcpSever.hpp

#pragma once

#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include "Log.hpp"
#include "nocopy.hpp"
#include "Comm.hpp"
#include "InetAddr.hpp"

const static int default_backlog = 6; // TODO

class TcpServer : public nocopy
{
public:
	TcpServer(uint16_t port) : _port(port), _isrunning(false)
	{
	}

	// 都是固定套路
	void Init()
	{
		// 1. 创建 socket, file fd, 本质是文件
		_listensock = socket(AF_INET, SOCK_STREAM, 0);
		if (_listensock < 0)
		{
			lg.LogMessage(Fatal, "create socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Fatal);
		}

		int opt = 1;
		setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR |
			SO_REUSEPORT, &opt, sizeof(opt));
		lg.LogMessage(Debug, "create socket success,
			sockfd: % d\n", _listensock);

		// 2. 填充本地网络信息并 bind
		struct sockaddr_in local;
		memset(&local, 0, sizeof(local));
		local.sin_family = AF_INET;
		local.sin_port = htons(_port);
		local.sin_addr.s_addr = htonl(INADDR_ANY);

		// 2.1 bind
		if (bind(_listensock, CONV(&local), sizeof(local)) != 0)
		{
			lg.LogMessage(Fatal, "bind socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Bind_Err);
		}

		lg.LogMessage(Debug, "bind socket success, sockfd: %d\n",
			_listensock);

		// 3. 设置 socket 为监听状态,tcp 特有的
		if (listen(_listensock, default_backlog) != 0)
		{
			lg.LogMessage(Fatal, "listen socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Listen_Err);
		}

		lg.LogMessage(Debug, "listen socket success,
			sockfd: % d\n", _listensock);
	}

	// Tcp 连接全双工通信的.
	void Service(int sockfd)
	{
		char buffer[1024];
		// 一直进行 IO
		while (true)
		{
			ssize_t n = read(sockfd, buffer, sizeof(buffer) - 1);
			if (n > 0)
			{
				buffer[n] = 0;
				std::cout << "client say# " << buffer <<
					std::endl;

				std::string echo_string = "server echo# ";
				echo_string += buffer;
				write(sockfd, echo_string.c_str(),
					echo_string.size());
			}
			else if (n == 0) // read 如果返回值是 0,表示读到了文件结尾(对端关闭了连接!)
			{
				lg.LogMessage(Info, "client quit...\n");
				break;
			}
			else
			{
				lg.LogMessage(Error, "read socket error, errno
					code: % d, error string : % s\n", errno, strerror(errno));
					break;
			}
		}
	}

	void ProcessConnection(int sockfd, struct sockaddr_in& peer)
	{
		// v2 多进程
		pid_t id = fork();
		if (id < 0)
		{
			close(sockfd);

			return;
		}
		else if (id == 0)
		{
			// child
			close(_listensock);
			if (fork() > 0)
				exit(0);
			InetAddr addr(peer); // 获取 client 地址信息
			lg.LogMessage(Info, "process connection: %s:%d\n",
				addr.Ip().c_str(), addr.Port());
			// 孙子进程,孤儿进程,被系统领养,正常处理
			Service(sockfd);
			close(sockfd);
			exit(0);
		}
		else
		{
			close(sockfd);
			pid_t rid = waitpid(id, nullptr, 0);
			if (rid == id)
			{
				// do nothing
			}
		}
	}

	void Start()
	{
		_isrunning = true;
		while (_isrunning)
		{
			// 4. 获取连接
			struct sockaddr_in peer;
			socklen_t len = sizeof(peer);
			int sockfd = accept(_listensock, CONV(&peer), &len);
			if (sockfd < 0)
			{
				lg.LogMessage(Warning, "accept socket error, errno
					code: % d, error string : % s\n", errno, strerror(errno));
					continue;
			}

			lg.LogMessage(Debug, "accept success, get n new
				sockfd: % d\n", sockfd);
				ProcessConnection(sockfd, peer);
		}
	}

	~TcpServer()
	{
	}

private:
	uint16_t _port;
	int _listensock; // TODO
	bool _isrunning;
};

引入InetAddr.hpp,方便后面打印消息。

2 -> V3 -Echo Server多线程版本

Thread.hpp

#pragma once

#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <pthread.h>
#include "Log.hpp"
#include "nocopy.hpp"
#include "Comm.hpp"
#include "InetAddr.hpp"

const static int default_backlog = 6; // TODO

class TcpServer : public nocopy
{
public:
	TcpServer(uint16_t port) : _port(port), _isrunning(false)
	{
	}

	// 都是固定套路
	void Init()
	{
		// 1. 创建 socket, file fd, 本质是文件
		_listensock = socket(AF_INET, SOCK_STREAM, 0);
		if (_listensock < 0)
		{
			lg.LogMessage(Fatal, "create socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Fatal);
		}

		int opt = 1;
		setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR |
			SO_REUSEPORT, &opt, sizeof(opt));
		lg.LogMessage(Debug, "create socket success,
			sockfd: % d\n", _listensock);

		// 2. 填充本地网络信息并 bind
		struct sockaddr_in local;
		memset(&local, 0, sizeof(local));
		local.sin_family = AF_INET;
		local.sin_port = htons(_port);
		local.sin_addr.s_addr = htonl(INADDR_ANY);

		// 2.1 bind
		if (bind(_listensock, CONV(&local), sizeof(local)) != 0)
		{
			lg.LogMessage(Fatal, "bind socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Bind_Err);
		}

		lg.LogMessage(Debug, "bind socket success, sockfd: %d\n",
			_listensock);

		// 3. 设置 socket 为监听状态,tcp 特有的
		if (listen(_listensock, default_backlog) != 0)
		{
			lg.LogMessage(Fatal, "listen socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Listen_Err);
		}

		lg.LogMessage(Debug, "listen socket success,
			sockfd: % d\n", _listensock);
	}

	class ThreadData
	{
	public:
		ThreadData(int sockfd, struct sockaddr_in addr)
			: _sockfd(sockfd), _addr(addr)
		{}

		~ThreadData()
		{}

	public:
		int _sockfd;
		InetAddr _addr;
	};

	// Tcp 连接全双工通信的.
	// 新增 static
	static void Service(ThreadData& td)
	{
		char buffer[1024];
		// 一直进行 IO
		while (true)
		{
			ssize_t n = read(td._sockfd, buffer, sizeof(buffer) -
				1);
			if (n > 0)
			{
				buffer[n] = 0;
				std::cout << "client say# " << buffer <<
					std::endl;

				std::string echo_string = "server echo# ";
				echo_string += buffer;
				write(td._sockfd, echo_string.c_str(),
					echo_string.size());
			}
			else if (n == 0) // read 如果返回值是 0,表示读到了文件结尾(对端关闭了连接!)
			{
				lg.LogMessage(Info, "client[%s:%d] quit...\n",
					td._addr.Ip().c_str(), td._addr.Port());
				break;
			}
			else
			{
				lg.LogMessage(Error, "read socket error, errno
					code: % d, error string : % s\n", errno, strerror(errno));
					break;
			}
		}
	}

	static void* threadExcute(void* args)
	{
		pthread_detach(pthread_self());
		ThreadData* td = static_cast<ThreadData*>(args);
		TcpServer::Service(*td);
		close(td->_sockfd);

		delete td;

		return nullptr;
	}

	void ProcessConnection(int sockfd, struct sockaddr_in& peer)
	{
		// v3 多线程
		InetAddr addr(peer);
		pthread_t tid;
		ThreadData* td = new ThreadData(sockfd, peer);
		pthread_create(&tid, nullptr, threadExcute, (void*)td);
	}

	void Start()
	{
		_isrunning = true;
		while (_isrunning)
		{
			// 4. 获取连接
			struct sockaddr_in peer;
			socklen_t len = sizeof(peer);
			int sockfd = accept(_listensock, CONV(&peer), &len);
			if (sockfd < 0)
			{
				lg.LogMessage(Warning, "accept socket error, errno
					code: % d, error string : % s\n", errno, strerror(errno));
					continue;
			}

			lg.LogMessage(Debug, "accept success, get n new
				sockfd: % d\n", sockfd);
				ProcessConnection(sockfd, peer);
		}
	}

	~TcpServer()
	{
	}

private:
	uint16_t _port;
	int _listensock; // TODO
	bool _isrunning;
};

使用最原始的接口,使用内部ThreadData类。

3 -> V3-1 -多线程远程命令执行

Command.hpp

  • 命令类,用来执行命令,并获取结果。
  • 这里暂停,做一个多线程的小业务。
#pragma once

#include <iostream>
#include <string>
#include <set>
#include <unistd.h>

class Command
{
private:
public:
	Command() {}

	Command(int sockfd) : _sockfd(sockfd)
	{
		// 限定一下命令的个数和范围
		_safe_command.insert("ls");
		_safe_command.insert("pwd");
		_safe_command.insert("ls -l");
		_safe_command.insert("ll");
		_safe_command.insert("touch");
		_safe_command.insert("who");
		_safe_command.insert("whoami");
	}

	bool IsSafe(const std::string& command)
	{
		auto iter = _safe_command.find(command);
		if (iter == _safe_command.end()) 
			return false; // 要执行的命令不 set 中,不安全
		else 
			return true;
	}

	std::string Execute(const std::string& command)
	{
		if (!IsSafe(command)) 
			return "unsafe";

		FILE* fp = popen(command.c_str(), "r");
		if (fp == nullptr)
			return std::string();

		char buffer[1024];
		std::string result;
		while (fgets(buffer, sizeof(buffer), fp))
		{
			result += buffer;
		}

		pclose(fp);

		return result;
	}

	std::string RecvCommand()
	{
		char line[1024];
		ssize_t n = recv(_sockfd, line, sizeof(line) - 1, 0); 
		if (n > 0)
		{
			line[n] = 0;
			return line;
		}
		else
		{
			return std::string();
		}
	}

	void SendCommand(std::string result)
	{
		if (result.empty()) result = "done"; // 主要是有些命令没有结果,比如 touch
			send(_sockfd, result.c_str(), result.size(), 0);
	}

	~Command()
	{
	}

private:
	std::set<std::string> _safe_command;
	int _sockfd;
	std::string _command;
};

TcpSever.hpp

#pragma once

#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <pthread.h>
#include "Log.hpp"
#include "nocopy.hpp"
#include "Comm.hpp"
#include "InetAddr.hpp"
#include "Command.hpp" // 引入命令执行

const static int default_backlog = 6; // TODO

class TcpServer : public nocopy
{
public:
	TcpServer(uint16_t port) : _port(port), _isrunning(false)
	{
	}

	// 都是固定套路
	void Init()
	{
		// 1. 创建 socket, file fd, 本质是文件
		_listensock = socket(AF_INET, SOCK_STREAM, 0);
		if (_listensock < 0)
		{
			lg.LogMessage(Fatal, "create socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Fatal);
		}

		int opt = 1;
		setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR |
			SO_REUSEPORT, &opt, sizeof(opt));
		lg.LogMessage(Debug, "create socket success,
			sockfd: % d\n", _listensock);

		// 2. 填充本地网络信息并 bind
		struct sockaddr_in local;
		memset(&local, 0, sizeof(local));
		local.sin_family = AF_INET;
		local.sin_port = htons(_port);
		local.sin_addr.s_addr = htonl(INADDR_ANY);

		// 2.1 bind
		if (bind(_listensock, CONV(&local), sizeof(local)) != 0)
		{
			lg.LogMessage(Fatal, "bind socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Bind_Err);
		}

		lg.LogMessage(Debug, "bind socket success, sockfd: %d\n",
			_listensock);

		// 3. 设置 socket 为监听状态,tcp 特有的
		if (listen(_listensock, default_backlog) != 0)
		{
			lg.LogMessage(Fatal, "listen socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Listen_Err);
		}

		lg.LogMessage(Debug, "listen socket success,
			sockfd: % d\n", _listensock);
	}

	class ThreadData
	{
	public:
		ThreadData(int sockfd, struct sockaddr_in addr)
			: _sockfd(sockfd), _addr(addr)
		{
		}

		~ThreadData()
		{
		}

	public:
		int _sockfd;
		InetAddr _addr;
	};

	// Tcp 连接全双工通信的.
	// 新增 static
	static void Service(ThreadData& td)
	{
		char buffer[1024];
		// 一直进行 IO
		while (true)
		{
			Command command(td._sockfd);
			std::string commandstr = command.RecvCommand();
			if (commandstr.empty())
				return;

			std::string result = command.Execute(commandstr);
			command.SendCommand(result);
		}
	}

	static void* threadExcute(void* args)
	{
		pthread_detach(pthread_self());
		ThreadData* td = static_cast<ThreadData*>(args);
		TcpServer::Service(*td);
		close(td->_sockfd);

		delete td;

		return nullptr;
	}

	void ProcessConnection(int sockfd, struct sockaddr_in& peer)
	{
		// v3 多线程
		InetAddr addr(peer);
		pthread_t tid;
		ThreadData* td = new ThreadData(sockfd, peer);
		pthread_create(&tid, nullptr, threadExcute, (void*)td);
	}

	void Start()
	{
		_isrunning = true;
		while (_isrunning)
		{
			// 4. 获取连接
			struct sockaddr_in peer;
			socklen_t len = sizeof(peer);
			int sockfd = accept(_listensock, CONV(&peer), &len);
			if (sockfd < 0)
			{
				lg.LogMessage(Warning, "accept socket error, errno
					code: % d, error string : % s\n", errno, strerror(errno));
					continue;
			}

			lg.LogMessage(Debug, "accept success, get n new
				sockfd: % d\n", sockfd);
				ProcessConnection(sockfd, peer);
		}
	}

	~TcpServer()
	{
	}

private:
	uint16_t _port;
	int _listensock; // TODO
	bool _isrunning;
};

4 -> V4 -Echo Server线程池版本

引入系统部分的线程池,进行简单的业务处理。

TcpServer.hpp

#pragma once

#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <pthread.h>
#include <functional>
#include "Log.hpp"
#include "nocopy.hpp"
#include "Comm.hpp"
#include "InetAddr.hpp"
#include "ThreadPool.hpp"

const static int default_backlog = 6; // TODO

class TcpServer : public nocopy
{
public:
	TcpServer(uint16_t port) : _port(port), _isrunning(false)
	{
	}

	// 都是固定套路
	void Init()
	{
		// 1. 创建 socket, file fd, 本质是文件
		_listensock = socket(AF_INET, SOCK_STREAM, 0);
		if (_listensock < 0)
		{
			lg.LogMessage(Fatal, "create socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Fatal);
		}

		int opt = 1;
		setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR |
			SO_REUSEPORT, &opt, sizeof(opt));
		lg.LogMessage(Debug, "create socket success,
			sockfd: % d\n", _listensock);

		// 2. 填充本地网络信息并 bind
		// struct sockaddr_in local;
		memset(&local, 0, sizeof(local));
		local.sin_family = AF_INET;
		local.sin_port = htons(_port);
		local.sin_addr.s_addr = htonl(INADDR_ANY);

		// 2.1 bind
		if (bind(_listensock, CONV(&local), sizeof(local)) != 0)
		{
			lg.LogMessage(Fatal, "bind socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Bind_Err);
		}

		lg.LogMessage(Debug, "bind socket success, sockfd: %d\n",
			_listensock);

		// 3. 设置 socket 为监听状态,tcp 特有的
		if (listen(_listensock, default_backlog) != 0)
		{
			lg.LogMessage(Fatal, "listen socket error, errno
				code: % d, error string : % s\n", errno, strerror(errno));
				exit(Listen_Err);
		}

		lg.LogMessage(Debug, "listen socket success,
			sockfd: % d\n", _listensock);
	}

	// Tcp 连接全双工通信的.
	void Service(int sockfd, InetAddr addr)
	{
		char buffer[1024];
		// 一直进行 IO
		while (true)
		{
			ssize_t n = read(sockfd, buffer, sizeof(buffer) - 1);
			if (n > 0)
			{
				buffer[n] = 0;
				std::cout << "client say# " << buffer <<
					std::endl;

				std::string echo_string = "server echo# ";
				echo_string += buffer;
				write(sockfd, echo_string.c_str(),
					echo_string.size());
			}

			else if (n == 0) // read 如果返回值是 0,表示读到了文件结尾(对端关闭了连接!)
			{
				lg.LogMessage(Info, "client[%s:%d] quit...\n",
					addr.Ip().c_str(), addr.Port());
				break;
			}
			else
			{
				lg.LogMessage(Error, "read socket error, errno
					code: % d, error string : % s\n", errno, strerror(errno));
					break;
			}
		}
	}

	void ProcessConnection(int sockfd, struct sockaddr_in& peer)
	{
		using func_t = std::function<void()>;
		InetAddr addr(peer);
		func_t func = std::bind(&TcpServer::Service, this, sockfd,
			addr); // 这里不能 auto
		ThreadPool<func_t>::GetInstance()->Push(func);
	}

	void Start()
	{
		_isrunning = true;
		while (_isrunning)
		{
			// 4. 获取连接
			struct sockaddr_in peer;
			socklen_t len = sizeof(peer);
			int sockfd = accept(_listensock, CONV(&peer), &len);
			if (sockfd < 0)
			{
				lg.LogMessage(Warning, "accept socket error, errno
					code: % d, error string : % s\n", errno, strerror(errno));
					continue;
			}

			lg.LogMessage(Debug, "accept success, get n new
				sockfd: % d\n", sockfd);
				ProcessConnection(sockfd, peer);
		}

		_isrunning = false;
	}

	~TcpServer()
	{
	}

private:
	uint16_t _port;
	int _listensock; // TODO
	bool _isrunning;
};

感谢各位大佬支持!!!

互三啦!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

为什么可视化大屏要有动态效果,都有哪些类型的效果。

可视化大屏已成为企业和组织展示关键信息的重要工具。这些大屏不仅需要清晰地传达数据&#xff0c;还要吸引观众的注意力并提供深刻的洞察。动态效果在这一过程中扮演着至关重要的角色。 动态效果的重要性 动态效果在可视化大屏中的应用&#xff0c;基于以下几个核心原因 吸…

【C/C++】字符/字符串函数(0)(补充)——由ctype.h提供

零.导言 除了字符分类函数&#xff0c;字符转换函数也是一类字符/字符串函数。 C语言提供了两种字符转换函数&#xff0c;分别是 toupper &#xff0c; tolower。 一.什么是字符转换函数&#xff1f; 顾名思义&#xff0c;即转换字符的函数&#xff0c;如大写字母转小写字母&am…

Hive数据库操作语法

数据类型 内部表和外部表 内部表 &#xff08;CREATE TABLE table_name ......&#xff09;未被external关键字修饰的即是内部表&#xff0c; 即普通表。 内部表又称管理表,内部表数据存储的位置由hive.metastore.warehouse.dir参数决定&#xff08;默认&#xff1a;/user/h…

线程基础知识、jmm(Java内存模型)

目录 线程基础知识 并发与并行 进程和线程 线程优先级 创建线程的方式主要有三种 休眠 作出让步 join() 方法 线程协作注意什么 理解线程状态 选择合适的协作工具 共享资源的访问控制 避免竞争条件 创建线程几种方式 线程状态&#xff0c;状态之间切换 新建&…

图解大模型训练系列:序列并行2,DeepSpeed Ulysses

最近已有不少大厂都在秋招宣讲&#xff0c;也有一些已在 Offer 发放阶段了。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行…

MP4650模块改为固定电压记录

目标 这种电源模块&#xff0c;可调电位器质量不太好&#xff0c;可调输出电压改为固定电压。 方法 步骤 按照下图&#xff0c;将计算得到的R1 补到 待添加电阻处。 结论 作者使用输出5V&#xff0c;R1电阻使用5.1K&#xff0c;得到输出电压4.8V&#xff1b; 测试输出电流1A…

51单片机教程(二)- 创建项目

1 创建项目 创建项目存储文件夹&#xff1a;C51Project 打开Keil5软件&#xff0c;选择 Project -> New uVision Project&#xff1a; 选择项目路径&#xff0c;即刚才创建的文件夹 选择芯片&#xff0c;选择 Microchip&#xff08;微型集成电路&#xff09;&#xff0…

STM32 HAL库 SPI驱动1.3寸 OLED屏幕

目录 参考硬件引脚与接线 点亮屏幕CubeMX 配置OLED 驱动程序代码 参考 基于STM32F103C8T6最小系统板HAL库CubeMX SPI驱动7针 OLED显示屏&#xff08;0.96寸 1.3寸通用&#xff09;0.96 oled HAL库驱动 SPI STM32SPI驱动0.96/1.3寸 OLED屏幕&#xff0c;易修改为DMA控制STM32驱…

通过分解质因数求若干个数的最小公倍数

求最小公倍数的常规方法回顾 暴力枚举法 long long work(long long a,long long b) {for(long long imax(a,b);;i)if(i%a0&&i%b0)return i; }大数翻倍法 long long work(long long a,long long b) {if(a<b) swap(a,b);for(long long ia;;ia) // i 是 a 的倍数&#…

突出显示与条件匹配的列值

Goto Appearance and Conditional Formatting 外观和条件格式 突出显示与条件匹配的列值 本教程说明如何将条件格式应用于 GridControl 中的 Market Share 列&#xff0c;以突出显示与特定条件匹配的单元格。此示例突出显示小于 20% 的 Market Share 列值。 要在设计时创建新…

node.js下载、安装、设置国内镜像源(永久)(Windows11)

目录 node-v20.18.0-x64工具下载安装设置国内镜像源&#xff08;永久&#xff09; node-v20.18.0-x64 工具 系统&#xff1a;Windows 11 下载 官网https://nodejs.org/zh-cn/download/package-manager 版本我是跟着老师选的node-v20.18.0-x64如图选择 Windows、x64、v20.18…

嵌入式开发教程之Linux下IO流

一、文件的概念和类型 文件基础&#xff1a; 概念&#xff1a;一组相关数据的有序集合&#xff0c;文件名、路径。通过文件名指定访问什么文件。 文件类型&#xff1a; 常规文件 r&#xff0c;分为&#xff1a;普通文件&#xff0c;文本文件&#xff08;可见字符&#xff09…

【Python】Python自习课:第一个python程序

【Python】Python自习课&#xff1a;第一个python程序

MySQL【二】

查询列 SELECT [ALL | DISTINCT ] * | 列名1[,……列名n] FROM 表名; 查询所有选课学生的学号&#xff0c;结果去除重复值 select distinct sno from sc; 选择行 查询满足条件的数据集 SELECT 字段列表 FROM 表名 WHERE 查询条件 查询不属于数学系或外国语系的学生全部信息 …

#渗透测试#SRC漏洞挖掘# 信息收集-Shodan进阶之Mongodb未授权访问

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

Redis 位图实现签到之长时间未签到预警

#目前通行系统项目中有一个新需求【通过对通行记录数据定时分析&#xff0c;查询出长时间没 有刷卡/刷脸通行的学生】 #一看到通行签到相关&#xff0c;就想到了redis的位图&#xff0c;理由也有很多帖子说明了&#xff0c;最大优点占用空间小。 一.redis命令行 SETBIT&#…

python mac vscode 脚本文件的运行

切换到脚本文件的目录下 路径的修改 当前文件组织形式&#xff1a; 脚本文件在文件夹下&#xff1a; 赋予权限&#xff1a;chmod x ./scripts/fscd_test.sh 运行&#xff1a;./scripts/fscd_test.sh

人脑与机器连接:神经科技的伦理边界探讨

内容概要 在当今科技飞速发展的时代&#xff0c;人脑与机器连接已成为一个引人注目的前沿领域。在这一背景下&#xff0c;神经科技的探索为我们打开了一个全新的世界&#xff0c;从脑机接口到人工智能的飞跃应用&#xff0c;不仅加速了技术的进步&#xff0c;更触动了我们内心…

[论文阅读] | 智能体长期记忆

更新记录&#xff1a; 2024.11.2 人大高瓴长期记忆综述 文章目录 人大高瓴长期记忆综述智能体与环境交互记忆的来源/形式/操作来源&#xff1a;(1)当前任务历史信息 (2)其他任务的信息 (3)外部知识形式&#xff1a;如何表达记忆的内容&#xff0c;通过(1)文本 (2)参数(训练到模…

R6:LSTM实现糖尿病探索与预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、实验目的&#xff1a; 学习使用LSTM对糖尿病进行探索预测 二、实验环境&#xff1a; 语言环境&#xff1a;python 3.8编译器&#xff1a;Jupyter notebook…