基于Linux的远程操作C语言实现(client and server)

需求

在Linux上利用流套接字提供客户端和服务端面向连接的交互。进行登陆验证、查看服务器列表、下载文件、远程执行命令的几个操作。

设计

  • 每次请求客户端首先发出一个报头,得到服务端的响应后确保连接的正确建立,之后开始传文件。
  • 对于下载文件操作:客户端输入一个相对路径或者绝对路径以及文件名,等到服务端响应一个确认报文后开始进行收文件。其中文件的传递利用二进制流的形式发送,这样的优点是能够将文件分成许多块发送且能够方便客户端读取。
  • 对于执行命令操作服务端通过客户端传来的命令,将其切割成各个命令以及参数块,之后利用fork以及exec函数族的形式让子进程执行改命令。要注意的是,通过exec执行的命令很难与其他命令嵌套,比如我们要把操作结果返回给客户端需要用到文件重定向,这里需要使用system函数,其内部实现是exec+fork+文件;能够轻易把传来的命令正确执行最后将结果重定向到文件中reply给客户端。

报文设计:

在这里插入图片描述

实现

服务端:

#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>      // 提供属性操作函数 
#include <sys/types.h>     // 提供mode_t 类型 
#include <malloc.h>     
#include <fcntl.h>  
#include <sys/socket.h>      
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <dirent.h>            // 提供目录流操作函数  

#define PORT	56193

#define MAX_UNAME   8
#define MAX_PASSWD  8
#define MAX_BUF_SZ  1024
#define MAX_CMD_SZ  20

#define TYPE_LOGIN  1
#define TYPE_READ 2
#define TYPE_EXIT 3
#define TYPE_EXEC_CMD 4
#define TYPE_GET_FILE 5
#define TYPE_NOT_FILE 6
#define TYPE_YES_FILE 7

struct hdr_st{
   
    unsigned short type;
    unsigned short len;
};

void scan_dir(char *dir, char *strbuf, int bufsz)   // 定义目录扫描函数  
{
     
    DIR *dp;                      // 定义子目录流指针  
    struct dirent *entry;         // 定义dirent结构指针保存后续目录  
    struct stat statbuf;          // 定义statbuf结构保存文件属性  
    int sz, remain = bufsz;
    char *pos = strbuf;

    if((dp = opendir(dir)) == NULL) // 打开目录,获取子目录流指针,判断操作是否成功  
    {
     
        puts("can't open dir.");  
        return;  
    }  
    chdir (dir);                     // 切换到当前目录  
    while((entry = readdir(dp)) != NULL)  // 获取下一级目录信息,如果未否则循环  
    {
     
        lstat(entry->d_name, &statbuf); // 获取下一级成员属性  
        if(S_IFDIR &statbuf.st_mode)    // 判断下一级成员是否是目录  
        {
     
            if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0)  
              continue;  
        }
        sz = strlen(entry->d_name);
        if(sz < remain){
   
            remain -= sz;
            sprintf(pos, "%s\n",  entry->d_name);  // 输出属性不是目录的成员  
            pos += (sz+1);
        }else return ;
    }  
    chdir("..");                                                  // 回到上级目录  
    closedir(dp);                                                 // 关闭子目录流  
}  

void split(char cmd_list[][MAX_CMD_SZ], char *cmd, int *sz) {
   
	int i, j, len, flag = 0;
	len = strlen(cmd);
	*sz = 0;
	j = 0;
	for (i = 0; i < len; i++) {
   
		if (cmd[i] == ' ' && i && cmd[i-1] != ' ') {
   
			cmd_list[*sz][j] = 0;
			*sz = *sz + 1;
			j = 0;
			flag = 0;
		} else if (cmd[i] != ' ') {
   
			cmd_list[*sz][j++] = cmd[i];
			flag = 1;
		}
	}
	if (flag) {
   
		cmd_list[*sz][j] = 0;
		*sz = *sz + 1;
	}
}

int do_login(int sAccept)
{
   
char usrname[MAX_UNAME];
char passwd[MAX_PASSWD];
int sz;

    printf("Receive Login request!\n");
    /* TODO here do not handle the sending delay */
	sz = recv(sAccept, usrname, MAX_UNAME, 0);
    if(sz < 0){
   
       printf("Did not receive the enough Message in login.\n");
       return 0;
    }

    sz = recv(sAccept, passwd, MAX_UNAME, 0);
    if(sz < 0){
   
       printf("Did not receive the enough Message in login.\n");
       return 0;
    }
	
	if (strcmp(usrname, "root") != 0 || strcmp(passwd, "123456") != 0) {
   
		return 0;
	}
	
	printf("User name :%s\n", usrname);
    	printf("passwd: %s\n", passwd);
	
	return 1;
}

void do_get_file_list(int sockfd) {
   
	char file_list[MAX_BUF_SZ];
	scan_dir(".", file_list, MAX_BUF_SZ - 1);
	if ( send(sockfd, &file_list, sizeof(file_list), 0) < 0 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值