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

socket远程命令通信简单实现

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、代码示例?
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

socket远程命令通信简单实现
内核版本5.10
cli端连接上ser端后,ser发送给cli端命令执行。
cli支持命令:
CMD_TYPE_TEST :测试,字符串通信
CMD_TYPE_EXEC:执行程序
CMD_TYPE_DOWNLOAD:下载文件
CMD_TYPE_UPLOAD:上传文件

上传和下载暂未实现。

提示:以下是本篇文章正文内容,下面案例可供参考

一、代码示例?

socket_cmd.h

#ifndef __SOCKET_CMD_H__
#define __SOCKET_CMD_H__typedef enum {CMD_TYPE_TEST = 0x1100,CMD_TYPE_EXEC,CMD_TYPE_DOWNLOAD,CMD_TYPE_UPLOAD,CMD_TYPE_MAX,
} cmd_type_t;typedef enum {OP_TYPE_TEST = 0x2100,OP_TYPE_REQ,OP_TYPE_REQ_WAIT,OP_TYPE_ACK,OP_TYPE_FAIL,OP_TYPE_MAX,
} op_type_t;struct s_cmd
{int cmd;int op;char msg[256];
};#endif

socket_cmd_ser.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>#include "socket_cmd.h"#define SERVER_IP "127.0.0.1" // 服务器的 IP 地址
#define SERVER_PORT 8080       // 服务器的端口号int ser_sock_create(char * addr, int port, int listen_num)
{char s_ip[16] = {0};int sockfd;int clifd;struct sockaddr_in server_addr = {0}; struct sockaddr_in client_addr = {0};char cmd_buf[512] = {0};int ret = 0;int addr_len = 0;if(addr == NULL || port > 65535 || port < 0 || listen_num <= 0 || listen_num > 1024){return -1;}printf("addr = %s, port = %d, listen_num = %d\n", addr, port, listen_num);memcpy(s_ip, addr, strnlen(addr, 16));// 创建套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("socket creation failed");return -1;}// Set the SO_REUSEADDR optionint optval = 1;if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {perror("Setsockopt failed");close(sockfd);return 1;}// 设置客户端地址信息server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port); // 客户端绑定的端口号server_addr.sin_addr.s_addr = inet_addr(s_ip); // 绑定所有可用接口// 绑定套接字到客户端地址if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("bind failed");close(sockfd);return -1;}addr_len = sizeof(client_addr);// 获取并打印绑定的 IP 地址和端口号if (getsockname(sockfd, (struct sockaddr *)&server_addr, &addr_len) == -1) {perror("getsockname failed");close(sockfd);return -1;}char ip_str[INET_ADDRSTRLEN];inet_ntop(AF_INET, &server_addr.sin_addr, ip_str, sizeof(ip_str));printf("ser bind %s:%d\n", ip_str, ntohs(server_addr.sin_port));// 开始监听连接if (listen(sockfd, listen_num) < 0) {perror("Listen failed");return -1;}clifd = accept(sockfd, NULL, NULL);if (clifd < 0) {perror("Accept failed");return -1;}// 这里可以添加发送和接收数据的代码while(1){memset(cmd_buf, 0, sizeof(cmd_buf));struct s_cmd cmd = {0};cmd.cmd = CMD_TYPE_TEST;cmd.op = OP_TYPE_TEST;memcpy(cmd.msg, "hello cmd", strnlen( "hello cmd", 128));memcpy(cmd_buf, &cmd, sizeof(cmd));ssize_t send_received = send(clifd, cmd_buf, sizeof(cmd) , MSG_NOSIGNAL);//ssize_t send_received = write(clifd, cmd_buf, sizeof(cmd_buf) - 1);printf("send_received = %d\n", send_received);if (send_received == -1) {if (errno == EPIPE) {printf("Client disconnected.\n");} else {perror("Send failed");}close(clifd);return -1;}usleep(3* 1000 * 1000);}// 关闭套接字close(sockfd);
}int main() {int sockfd;ser_sock_create("0.0.0.0", 9090, 1);return 0;
}

socket_cmd_cli.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#include "socket_cmd.h"#define SERVER_IP "127.0.0.1" // 服务器的 IP 地址
#define SERVER_PORT 8080       // 服务器的端口号
#define CLIENT_PORT 19091       // 客户端绑定的端口号#define MAX_ARGS  10int do_str_execvp(char * exec_cmd)
{char *args[MAX_ARGS];int int arg_count = 0;char cmd_copy[256] = {0};strncpy(cmd_copy, exec_cmd,strnlen(exec_cmd, 256));char *token = strtok(cmd_copy, " "); // 默认以空格分隔// 提取命令和参数while (token != NULL && arg_count < MAX_ARGS - 1) {args[arg_count++] = token;token = strtok(NULL, " ");}args[arg_count] = NULL; // execvp 的参数数组必须以 NULL 结尾// 使用 execvp 执行命令if (execvp(args[0], args) == -1) {perror("execvp failed");exit(EXIT_FAILURE);}// 如果 execvp 成功,下面的代码将不会执行return 0;
}int do_cmd_exec(char* exec_cmd)
{int pid_t pid;if(NULL == exec_cmd){return -1;    }pid = fork()if(pid < 0){printf("fork failed\n");return -1;}else if(pid == 0){// 子进程do_str_execvp(exec_cmd);}else{// 父进程}}int cli_cmd_dispatch(struct s_cmd * cmd)
{struct s_cmd* tmp_cmd = NULL;if(cmd == NULL){return -1;}tmp_cmd = malloc(sizeof(struct s_cmd));if(tmp_cmd == NULL){return -1;}memcpy(tmp_cmd, cmd, sizeof(struct s_cmd));switch(tmp_cmd->cmd){case CMD_TYPE_TEST:break;case CMD_TYPE_EXEC:break;case CMD_TYPE_DOWNLOAD:break;case CMD_TYPE_UPLOAD:break;default:break;}free(tmp_cmd);return 0;
}int cli_check_cmd_valid(struct s_cmd * cmd)
{if(cmd == NULL){return -1;}return 0;
}int cli_sock_create(char * seraddr, int serport, char * cliaddr, int cliport)
{char s_ip[16] = {0};char c_ip[16] = {0};int sockfd;struct sockaddr_in server_addr = {0}; struct sockaddr_in client_addr = {0};char cmd_buf[512] = {0};int ret = 0;int addr_len = 0;if(seraddr == NULL || serport > 65535 || serport < 0 || cliport < 0 || cliport > 65535){return -1;}if(cliaddr == NULL){memcpy(c_ip, "0.0.0.0", strnlen("0.0.0.0", 16));}else{memcpy(c_ip, cliaddr, strnlen(cliaddr, 16));}memcpy(s_ip, seraddr, strnlen(seraddr, 16));// 创建套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}// 设置客户端地址信息client_addr.sin_family = AF_INET;client_addr.sin_port = htons(CLIENT_PORT); // 客户端绑定的端口号client_addr.sin_addr.s_addr = inet_addr(c_ip); // 绑定所有可用接口// 绑定套接字到客户端地址if (bind(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr)) < 0) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);}addr_len = sizeof(client_addr);// 获取并打印绑定的 IP 地址和端口号if (getsockname(sockfd, (struct sockaddr *)&client_addr, &addr_len) == -1) {perror("getsockname failed");close(sockfd);exit(EXIT_FAILURE);}char ip_str[INET_ADDRSTRLEN];inet_ntop(AF_INET, &client_addr.sin_addr, ip_str, sizeof(ip_str));printf("cli bind %s:%d\n", ip_str, ntohs(client_addr.sin_port));// 设置服务器地址信息memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(serport);server_addr.sin_addr.s_addr = inet_addr(s_ip);// 连接到服务器if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("connection to server failed");close(sockfd);exit(EXIT_FAILURE);}printf("connetct to ser %s:%d\n", s_ip, serport);// 这里可以添加发送和接收数据的代码while(1){struct s_cmd cmd = {0};memset(cmd_buf, 0, sizeof(cmd_buf));ssize_t bytes_received = recv(sockfd, cmd_buf, sizeof(struct s_cmd), 0);if (bytes_received < 0) {perror("recv failed");close(sockfd);return -1;} else if (bytes_received == 0) {printf("ser closed\n");close(sockfd);return 0;}memcpy(&cmd, cmd_buf, sizeof(struct s_cmd));printf("bytes_received = %d, cmd.cmd = 0x%x, cmd.op = 0x%x, cmd.msg = %s\n", bytes_received, cmd.cmd, cmd.op, cmd.msg);if(cli_check_cmd_valid(&cmd) == 0){cli_cmd_dispatch(&cmd);}}// 关闭套接字close(sockfd);
}int main() {int sockfd;cli_sock_create("127.0.0.1", 9090, NULL, 0);return 0;
}

Makefile

all:gcc socket_cmd_cli.c -o socket_cmd_cli -ggcc socket_cmd_ser.c -o socket_cmd_ser -gclean:rm -f socket_cmd_cli socket_cmd_ser

总结

socket远程命令通信简单实现,目标支持命令:测试,字符串通信,执行程序,下载文件,上传文件。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 《Nginx 负载均衡详解》
  • ‌‌雅诗兰黛、‌‌兰蔻等美妆大品牌的营销策略是什么?
  • pandas中loc和iloc的区别
  • 【排序算法】之基数排序
  • kafka原理剖析及实战演练
  • 手机玩机常识-------谷歌系列机型解锁bl详细步骤 其他机型可以借鉴参考
  • Git 提取和拉取的区别在哪
  • 基于基础模型BERT与大语言模型ChatGLM3-6B实现文本分类、信息抽取、文本匹配等任务
  • wopop靶场漏洞挖掘练习
  • 解决:Module build failed (from ./node_modules/sass-loader/dist/cjs.js)问题
  • Go Playground 在线编程环境
  • Unity自带脚本之GameObject脚本
  • MariaDB基本知识汇总
  • 如何使用智能合约铸造 NFT —— 以 NftMarket 合约为例
  • 部署自己的对话大模型,使用Ollama + Qwen2 +FastGPT 实现
  • Angular 响应式表单 基础例子
  • Consul Config 使用Git做版本控制的实现
  • Javascript基础之Array数组API
  • js递归,无限分级树形折叠菜单
  • learning koa2.x
  • MaxCompute访问TableStore(OTS) 数据
  • node-glob通配符
  • npx命令介绍
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • React 快速上手 - 07 前端路由 react-router
  • Redis中的lru算法实现
  • SpriteKit 技巧之添加背景图片
  • vue总结
  • 分布式熔断降级平台aegis
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 免费小说阅读小程序
  • 区块链技术特点之去中心化特性
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​低代码平台的核心价值与优势
  • ​什么是bug?bug的源头在哪里?
  • # 安徽锐锋科技IDMS系统简介
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • ()、[]、{}、(())、[[]]命令替换
  • (6) 深入探索Python-Pandas库的核心数据结构:DataFrame全面解析
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (独孤九剑)--文件系统
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (详细文档!)javaswing图书管理系统+mysql数据库
  • (一)Kafka 安全之使用 SASL 进行身份验证 —— JAAS 配置、SASL 配置
  • (转)Windows2003安全设置/维护
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .net的socket示例
  • .NET连接MongoDB数据库实例教程
  • [8] CUDA之向量点乘和矩阵乘法