一种不需要客户端ip的命令行远程工具

项目地址:Academy remote system: 一种不需要客户端ip的命令行远程工具 - Gitee.com

项目介绍:

传统的远程命令行工具如ssh,scp都需要目标服务器的ip才可以连接。

我设计的这款命令行远程工具可以基于多个中间服务器进行远程,而不需要设置目标ip。

部分代码(20240317年更新)

academy_client-aca.c:

#include <stdio.h>
#include "yamlreader.h"
#include "codereader.h"
#include <string.h>
//#define DEBUGMODE
void show_copyright(void){printf("@copyright2024 Anchengan\n");
}
void show_help(void){printf("Help document for aca software:\n");printf("aca [authkey of remote client] [path to settings.yaml] [password of remote client]\n");printf("aca listenmode [path to settings.yaml]\n");
}
int is_path_in_ld_library_path(const char *path_to_check) {const char *ld_library_path = getenv("LD_LIBRARY_PATH");if (ld_library_path == NULL) {// 如果LD_LIBRARY_PATH未设置,则直接返回0(不在其中)return 0;}// 分割LD_LIBRARY_PATH并检查每个路径char *path_copy = strdup(ld_library_path); // 复制环境变量值char *token = strtok(path_copy, ":");while (token != NULL) {// 比较当前路径和要检查的路径if (strcmp(token, path_to_check) == 0) {free(path_copy); // 释放内存return 1; // 找到路径,返回1}token = strtok(NULL, ":"); // 继续查找下一个路径}free(path_copy); // 释放内存return 0; // 未找到路径,返回0
}
char* remove_char(const char* str, char c) {int count = 0;for (const char* p = str; *p; p++) {if (*p != c) {count++;}}// 分配足够的空间来存储新字符串char* result = (char*)malloc(count + 1);  // +1 为 '\0'if (!result) {return NULL;  // 内存分配失败}int i = 0;for (const char* p = str; *p; p++) {if (*p != c) {result[i++] = *p;}}result[i] = '\0';  // 确保新字符串以 '\0' 结尾return result;
}
int main(int argc, char *argv[]) {// 打印传递的参数if(argc-1==0){show_copyright();printf("Enter -h or --help after aca for help.\n");printf("Example:\naca -h\naca --help\n");return 0;}for(int i=1;i<=argc-1;i++){if(strcmp(argv[i],"-h")==0 || strcmp(argv[i],"--help")==0){show_copyright();show_help();return 0;}}if(argc-1>3){printf("Unknown usage of aca...\n");show_help();return 0;}int yamllength=strlen(argv[2]);if(yamllength<5 || argv[2][yamllength-5]!='.' || argv[2][yamllength-4]!='y' || argv[2][yamllength-3]!='a' || argv[2][yamllength-2]!='m' || argv[2][yamllength-1]!='l'){printf("Please check your path to settings.yaml!\n");printf("Example:./settings.yaml\n");show_help();return 0;}int islistenmode=0;if (strcmp(argv[1],"listenmode")==0){if(argc-1>2){printf("Unknown usage of aca...\n");show_help();return 0;}printf("listenmode setup successfully...\n");islistenmode=1;}else{printf("your authkey of remote client is:%s\n",argv[1]);}printf("setting env...\n");int env_return_value;const char *path_to_check = "./"; // 要检查的路径  const char *bashrc_path = getenv("HOME"); // 获取用户主目录if (bashrc_path == NULL) {perror("Error getting HOME environment variable");return EXIT_FAILURE;}// 拼接.bashrc文件的完整路径char full_path[1024];snprintf(full_path, sizeof(full_path), "%s/.bashrc", bashrc_path);// 打开.bashrc文件FILE *file = fopen(full_path, "r");if (file == NULL) {perror("Error opening ~/.bashrc");return EXIT_FAILURE;}// 要搜索的内容const char *search_content = "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./";char line[1024]; // 假设每行不会超过1023个字符// 逐行读取并搜索内容int found = 0; // 标记是否找到内容while (fgets(line, sizeof(line), file)) {if (strstr(line, search_content) != NULL) {
#ifdef DEBUGMODEprintf("Found the content in ~/.bashrc: %s", line);
#endiffound = 1; // 找到内容,设置标记break; // 如果只需要找到一次就退出循环}}// 关闭文件fclose(file);if (!is_path_in_ld_library_path(path_to_check) && !found) {  // 使用system()函数运行命令行命令env_return_value = system("echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./' >> ~/.bashrc");// 检查命令的退出码
#ifdef DEBUGMODEif (env_return_value == -1) {// system()函数调用失败// 在这种情况下,你可以查看errno来获取错误详情(需要包含errno.h头文件)perror("system() failed");} else if (WIFEXITED(env_return_value)) {// 命令正常退出,WEXITSTATUS(env_return_value)可以获取命令的退出状态printf("Command exited with status %d\n", WEXITSTATUS(env_return_value));} else if (WIFSIGNALED(env_return_value)) {// 命令因为接收到信号而终止,WTERMSIG(env_return_value)可以获取信号的编号printf("Command terminated by signal %d\n", WTERMSIG(env_return_value));}
#endifprintf("env set successfully...\n");printf("please run: source ~/.bashrc\n");return 0;}else if(!is_path_in_ld_library_path(path_to_check) && found){printf("please run: source ~/.bashrc\n");return 0;}#include "libsender.h"#include "libreceiver.h"printf("your path to settings.yaml is:%s\n",argv[2]);    printf("Reading settings.yaml...\n");struct item_ret* yaml_data = get_item(argv[2]);struct ip* ip_reader;struct port* port_reader;ip_reader=yaml_data->ip_items;port_reader=yaml_data->port_items;char mac_device[20];char c = ':';   strcpy(mac_device,yaml_data->mac_device);int iplength = 0;struct ip* ip_pin = ip_reader;while (ip_pin != NULL) {iplength++;ip_pin = ip_pin->next;}char send_ip_info[iplength*100];char send_port_info[iplength*100];while (ip_reader != NULL){printf("ip:%s\n", ip_reader->ip);strcat(send_ip_info,ip_reader->ip);strcat(send_ip_info,"-");ip_reader = ip_reader->next;for(int i=0;i<2;i++){printf("port:%s\n", port_reader->port);strcat(send_port_info,port_reader->port);strcat(send_port_info,"-");port_reader = port_reader->next;}}printf("settings.yaml read completed...\n");if(islistenmode){//waiting for connection...printf("Getting connecting code of this device...\n");struct device_ret* device_data=get_device_code(mac_device);char* device_code=device_data->mac_device;char* address_code=device_data->mac_address;printf("Connecting code of this device is:%s\n",device_code);char* password = remove_char(address_code, c);printf("Your password is:%s\n",password);Receiver(device_code,password,send_ip_info,send_port_info);}else{Sender(argv[1],argv[3],send_ip_info,send_port_info);//connecting...}return 0; 
}

academy_server-acade.go:

package main
import ("fmt""bufio""net""sync""io/ioutil""log""os""strconv""gopkg.in/yaml.v2"
)
type client struct {conn     net.Connconnid stringname     stringmessages chan  string
}
type Message struct {conn net.Connconnid stringSenderName stringContent    string
}
var (entering = make(chan client)leaving  = make(chan client)messages = make(chan Message) // 所有接收的消息
)
type Config struct {Database struct {Host     string `yaml:"host"`Port     int    `yaml:"port"`Port2    int    `yaml:"port2"`} `yaml:"database"`
}
func broadcast() {clients := make(map[string]client) // 键是客户端的名称,值是客户端结构体实例for {select {case msg := <-messages:// 将消息广播给除了发送者以外的所有客户端for _,cli := range clients {if cli.name != msg.SenderName && cli.connid==msg.connid {cli.messages<- msg.Content}}case newClient := <-entering:clients[newClient.name] = newClientcase leavingClient := <-leaving:delete(clients, leavingClient.name)close(leavingClient.messages)}}
}
func handleConn(conn net.Conn,connid string) {input := bufio.NewScanner(conn)var wg sync.WaitGroup// 创建一个新的客户端ch := make(chan string,1)  // 客户端的消息通道go clientWriter(conn, ch)cli := client{conn: conn, connid:connid,name: conn.RemoteAddr().String(), messages: ch}entering <- clifmt.Println(cli.name)wg.Add(1)go func() {defer wg.Done()for input.Scan() {messages <-Message{SenderName: cli.name, Content: input.Text(),conn:conn,connid:connid} // cli.name + ": " + input.Text()_, err := conn.Write([]byte("Received your message\n"))if err != nil {fmt.Println("Error writing to connection:", err.Error())break}}}()wg.Wait()leaving <- cliconn.Close()
}
func clientWriter(conn net.Conn, ch <-chan string) {for msg := range ch {fmt.Fprintln(conn, msg) // 注意:网络写入应该有错误处理}
}func main() {argCount := len(os.Args) - 1if argCount == 0 {fmt.Println("没有传递任何参数。")fmt.Println("acade -h")fmt.Println("acade --help")os.Exit(1) // 使用非零状态码退出,表示错误  }// 如果参数数量不符合预期(例如,你需要恰好2个参数),提前返回  if argCount != 1 {fmt.Printf("需要1个参数,但传递了%d个参数。\n", argCount)os.Exit(1) // 使用非零状态码退出,表示错误  }yamlfilename:=os.Args[1]if yamlfilename=="-h" || yamlfilename=="--help"{fmt.Println("acade [path to settings.yaml]")os.Exit(0)}// 读取YAML文件内容  yamlFile, err := ioutil.ReadFile(yamlfilename)if err != nil {log.Fatalf("无法读取YAML文件: %v", err)}// 解析YAML内容  var config Configerr = yaml.Unmarshal(yamlFile, &config)if err != nil {log.Fatalf("无法解析YAML内容: %v", err)}// 输出解析后的内容  fmt.Printf("Host: %s\n", config.Database.Host)fmt.Printf("Port: %d\n", config.Database.Port)fmt.Printf("Port2: %d\n", config.Database.Port2)Host:=config.Database.HostPort:=strconv.Itoa(config.Database.Port)Port2:=strconv.Itoa(config.Database.Port2)listener, err := net.Listen("tcp",Host+":"+Port)if err != nil {fmt.Println(err)return}listener2, err2 := net.Listen("tcp",Host+":"+Port2)if err2 != nil {fmt.Println(err2)return}go broadcast()go func(){for {conn, err := listener.Accept()if err != nil {fmt.Println(err)continue}go handleConn(conn,"1")}}()go func(){for{conn2, err2 := listener2.Accept()if err2 != nil {fmt.Println(err2)continue}go handleConn(conn2,"2")}}()for{}// 程序正常执行完毕,使用零状态码退出  os.Exit(0)
}

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

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

相关文章

【FPGA/IC】什么是模块化设计?

什么是模块化设计 FPGA/IC设计中根据模块层次的不同有两种基本的设计方法&#xff1a; 自下而上方法对设计进行逐次划分的过程是从基本单元出发的&#xff0c;设计树最末枝上的单元是已经设计好的基本单元&#xff0c;或者其他项目开发好的单元或者IP。该方法先对底层的功能块…

AI解答——DNS、DHCP、SNMP、TFTP、IKE、RIP协议

使用豆包帮助我解答计算机网络通讯问题—— 1、DHCP 服务器是什么&#xff1f; DHCP 服务器可是网络世界中的“慷慨房东”哦&#x1f923; 它的全称是 Dynamic Host Configuration Protocol&#xff08;动态主机配置协议&#xff09;服务器。 DHCP 服务器的主要任务是为网络中的…

探索发布-订阅模式的深度奥秘-实现高效、解耦的系统通信

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自&#xff1a;探索设计模式的魅力&#xff1a;探索发布-订阅模式的深度奥秘-…

Jest:JavaScript的单元测试利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

作品展示ETL

1、ETL 作业定义、作业导入、控件拖拽、执行、监控、稽核、告警、报告导出、定时设定 欧洲某国电信系统数据割接作业定义中文页面&#xff08;作业顶层&#xff0c;可切英文&#xff0c;按F1弹当前页面帮助&#xff09; 涉及文件拆分、文件到mysql、库到库、数据清洗、数据转…

Vue mqtt 附在线mqtt客户端地址 + 完整示例

mqtt&#xff1a;轻量级物联网消息推送协议。 目录 一、介绍 1、官方文档 1&#xff09;npm网 2) 中文网 MQTT中文网_MQTT 物联网接入平台-MQTT.CN 2、官方示例 二、准备工作 1、安装依赖包 2、示例版本 三、使用步骤 1、在单页面引入 mqtt 四、完整示例 tips 一、介…

渐开线花键环规的几种加工方法

小伙伴们大家好&#xff0c;今天咱们聊一聊渐开线花键环规的几种加工方法。 渐开线花键环规是在汽车、摩托车以及机械制造工业应用非常广泛的一种检测量具。它属于是一种内花键齿轮&#xff0c;其精度和表面粗糙度要求都比较高。采用的加工方法也比较多&#xff0c;下面详细看…

Python实战:网络请求库requests使用教程

1. 引言 在Python编程中&#xff0c;网络请求是常见且重要的操作之一。requests是Python中最流行的网络请求库之一&#xff0c;它基于urllib3&#xff0c;提供了简单的API来发送HTTP请求。requests库简化了HTTP通信的过程&#xff0c;使开发者能够轻松地发送请求、处理响应和处…

【爬虫逆向】Python逆向采集猫眼电影票房数据

进行数据抓包&#xff0c;因为这个网站有数据加密 !pip install jsonpathCollecting jsonpathDownloading jsonpath-0.82.2.tar.gz (10 kB)Preparing metadata (setup.py) ... done Building wheels for collected packages: jsonpathBuilding wheel for jsonpath (setup.py) .…

Android VINF

周末搞这玩意欲仙欲死&#xff0c;没办法只有看看。VINTF是供应商接口对象&#xff08;VINTF 对象&#xff09;&#xff0c;准确的说&#xff0c;这个是属于兼容性矩阵概念。。。有点想起了以前看过的一个电影&#xff0c;异次元杀阵。。。下面是谷歌官方的图。 本质上其实就是…

Go语言-关于 go get 和 go install

Go语言-关于 go get 和 go install 一直以来&#xff0c;我们通常都是通过 go get 来下载并安装包的。但从 Go 1.16 起&#xff0c;不推荐通过 go get 来安装包&#xff08;主要是说安装可执行文件&#xff09;&#xff0c;也就是说&#xff0c;go get 应该只是用来下载包&…

面试算法-41-打家劫舍

题目 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个房屋存放…

C++之类和对象(3)

目录 1. 再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit 2. static成员 2.1 概念 3. 友元 3.1 友元函数 3.2 友元类 4. 内部类 5. 匿名对象 6. 拷贝对象时编译器做出的优化 1. 再谈构造函数 1.1 构造函数体赋值 class Date { public:Date(int year2024…

Helm Chart部署最简SpringBoot到K8S(AWS EKS版)

目标 这里假设&#xff0c;我们已经基本会使用k8s的kubectl命令进行部署了&#xff0c;也已经会自己打docker镜像推送到AWS ECR上面去了。而且&#xff0c;已经在云上准备好了AWS ECR镜像库和AWS EKS的k8s集群了。 这个前提上面&#xff0c;我们今天使用Helm Chart项目准备k8s…

数据结构试卷第九套

1.时间复杂度 2.树&#xff0c;森林&#xff0c;二叉树的转换 2.1树转二叉树 给所有的兄弟节点之间加一条连线&#xff1b;去线&#xff0c;只保留当前根节点与第一个叶子节点的连线&#xff0c;删除它与其他节点之间的连线&#xff1b;然后根据左孩子右兄弟进行调整&#xf…

个人网站制作 Part 11 添加用户权限管理 | Web开发项目

文章目录 &#x1f469;‍&#x1f4bb; 基础Web开发练手项目系列&#xff1a;个人网站制作&#x1f680; 添加用户权限管理&#x1f528;使用Passport.js&#x1f527;步骤 1: 修改Passport本地策略 &#x1f528;修改用户模型&#x1f527;步骤 2: 修改用户模型 &#x1f528…

OpenFeign快速入门及使用

OpenFeign快速入门及使用 前言 需要先部署Nacos注册中心 1.导入依赖 代码如下&#xff1a; <!--openFeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></de…

医学数据分析中缺失值的处理方法

医学数据分析中缺失值的处理方法 &#xff08;为了更好的展示&#xff0c;在和鲸社区使用代码进行展示&#xff09; 医学数据分析中&#xff0c;缺失值是不可避免的问题。缺失值的存在会影响数据的完整性和准确性&#xff0c;进而影响分析结果的可靠性。因此&#xff0c;在进…

中创ET4410台式电桥固件升级工具(修复了列表扫描的BUG)

中创ET4410台式LCR数字电桥固件升级工具和最新版固件&#xff08;修复了列表扫描的BUG&#xff09; 中创ET4410 台式LCR数字电桥 简单开箱测评&#xff1a;https://blog.zeruns.tech/archives/763.html 之前买的中创ET4410台式LCR数字电桥固件有BUG&#xff08;胜利的VC4090C…

FREERTOS中断配置和临界段

本文基础内容参考的是正点原子的FREERTOS课程。 这是基于HAL库的 正点原子手把手教你学FreeRTOS实时系统 这是基于标准库的 正点原子FreeRTOS手把手教学-基于STM32 回顾STM32的中断 什么是中断&#xff1f; 中断优先级分组设置 Freertos中断分组 Freertos就是用的最后一种&…