【Linux】【SOCKET】简单远程控制

server端执行shell命令

popen()函数

popen()可以执行shell命令,并读取此命令的返回值;  
popen()函数通过创建一个 管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程。可以通过这个管道执行标准输入输出操作。
这个管道必须由pclose()函数关闭,pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose()返回的终止状态与shell已执行exit一样。

int execute(char* cmd,int sockfd,struct sockaddr_in client)
{
    char buf[BUFSIZE];
    FILE* fp;
    char* errbuf="command cannot execute\n";
    int ret;
    int counter;

    fp=NULL;
    counter=0;
    memset(buf,0,BUFSIZE);

    if ((fp = popen(cmd, "r")) == NULL)
    {
        perror("open failed!");
        ret=sendto(sockfd,errbuf,strlen(errbuf),0,(struct sockaddr*)&client,sizeof(struct sockaddr));
        return -1;
    }

    while((!feof(fp))&&(counter<2048))
    {
        buf[counter]=fgetc(fp);
        counter++;     
    }
    ret=sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&client,sizeof(struct sockaddr));
    if(0>ret)
        return -1;

    return 0;

}

UDP

server端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>


#define PORT 8900
#define BUFSIZE 2048

/**
 * @description: 将客户端内容作为命令执行,并发送给客户端
 * @param:cmd:待处理的命令
 *       :sockfd: 通讯的套接字
 *       :client:对应客户端地址
 * @return {*}:0 正确,-1 失败
 */

int execute(char* cmd,int sockfd,struct sockaddr_in client)
{
    char buf[BUFSIZE];
    FILE* fp;
    char* errbuf="command cannot execute\n";
    int ret;
    int counter;

    fp=NULL;
    counter=0;
    memset(buf,0,BUFSIZE);

    if ((fp = popen(cmd, "r")) == NULL)
    {
        perror("open failed!");
        ret=sendto(sockfd,errbuf,strlen(errbuf),0,(struct sockaddr*)&client,sizeof(struct sockaddr));
        return -1;
    }

    while((!feof(fp))&&(counter<2048))
    {
        buf[counter]=fgetc(fp);
        counter++;     
    }
    ret=sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&client,sizeof(struct sockaddr));
    if(0>ret)
        return -1;

    return 0;

}

int main(int argc,char** argv)
{
    // declare variable
    int sockfd;
    struct sockaddr_in serv, client;
    int opt;
    int ret;
    int len;
    char send_buf[BUFSIZE],recv_buf[BUFSIZE];

    // variable initialization
    sockfd=-1;
    opt=SO_REUSEADDR;
    ret=-1;
    len=-1;
    bzero(&serv,sizeof(struct sockaddr));
    bzero(&client,sizeof(struct sockaddr));
    bzero(send_buf,BUFSIZE);
    bzero(recv_buf,BUFSIZE);

    // create socket
    sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(0>sockfd)
    {
        perror("error in creating socket]n");
        exit(-1);
    }

    // set the socket
    // allow re-bind
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int));

    //set the value for serv
    serv.sin_family=AF_INET;
    serv.sin_addr.s_addr=INADDR_ANY;
    serv.sin_port=htons(PORT);

    // bind the socket serv
    ret=bind(sockfd,(struct sockaddr*)&serv,sizeof(struct sockaddr));
    if(0>ret)
    {
        perror("error in binding\n");
        exit(-1);
    }

    // begin communication
    len=sizeof(struct sockaddr);
    while(1)
    {
        memset(recv_buf,0,BUFSIZE);        
        ret=recvfrom(sockfd,recv_buf,BUFSIZE,0,(struct sockaddr*)&client,&len);
        if(0>ret)
        {
            perror("error in recving data\n");
            continue;
        }
        recv_buf[ret-1]='\0';
        if (0==strcmp(recv_buf,"quit"))
        {
            fprintf(stderr,"server is terminate by client\n");
            break;
        }
        
        execute(recv_buf,sockfd,client);

    }
    fprintf(stderr,"server is down\n");
    close(sockfd);
    
}

client端

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define BUFSIZE 2048

int usage(char *cmd)
{
    fprintf(stderr,"usage for %s\n:",cmd);
    fprintf(stderr,"%s ipaddr port\n",cmd);
}

int main(int argc,char** argv)
{
    int sockfd;
    struct sockaddr_in serv;
    char send_buf[BUFSIZE];
    char recv_buf[BUFSIZE];
    int len,ret;


    if (3!=argc)
    {
        usage(argv[0]);
        exit(-1);
    }

    // 初始化
    sockfd=-1;
    memset(&serv,0,sizeof(struct sockaddr));
    memset(send_buf,0,BUFSIZE);
    memset(recv_buf,0,BUFSIZE);


    // 建立套接字
    sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if (0>sockfd)
    {
        perror("create socket error\n");
        exit(-1);
    }

    // 设置服务器
    serv.sin_family=AF_INET;
    serv.sin_port=htons(atoi(argv[2]));
    serv.sin_addr.s_addr=inet_addr(argv[1]);
    

    while(1)
    {
       
        fprintf(stderr,"rms>>>");
        fgets(send_buf,BUFSIZE,stdin);
        ret=sendto(sockfd,send_buf,BUFSIZE,0,(struct sockaddr*)&serv,sizeof(struct sockaddr));
        if (0>ret)
        {
            perror("error in sending data\n");
            exit(-1);
        }
        send_buf[strlen(send_buf)-1]='\0';
        if(0==strcmp(send_buf,"quit"))
        {
            fprintf(stderr,"remote control terminate\n");
            break;
        }

        ret=recvfrom(sockfd,recv_buf,BUFSIZE,0,NULL,NULL);
        if (0>ret)
        {
            perror("error in recving data\n");
            exit(-1);
        }
        recv_buf[ret-1]='\0';

        fprintf(stderr,"%s\n",recv_buf);
    }
    

    // 通讯结束,关闭套接字
    close(sockfd);
    
}

TCP

server端

/*tcpserver.c*/
#include<stdlib.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netdb.h>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <printf.h>

#define PORT 8900

int execute(char* command,char* buf);

int main(int argc,char** argv)
{
	struct sockaddr_in server;
	struct sockaddr_in client;
	int len;
	int port;
	int listend;
	int connectd;
	int sendnum;
	int opt;
	int recvnum;
	char send_buf[2048];
	char recv_buf[2048];
	char cmd[2048];

	port= PORT;
	opt = SO_REUSEADDR;

	//1. create socket
	if (-1==(listend=socket(AF_INET,SOCK_STREAM,0)))
	{
		perror("create listen socket error\n");
		exit(1);
	}

	setsockopt(listend,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

	memset(&server,0,sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(INADDR_ANY);
	server.sin_port = htons(port);

	//2. bind
	if (-1==bind(listend,(struct sockaddr *)&server,sizeof(struct sockaddr)))	
	{
		perror("bind error\n");
		exit(1);
	}

	//3. listen
	if (-1==listen(listend,5))
	{
		perror("listen error\n");
		exit(1);
	}

	while (1)
	{
		// 4. accept
		connectd=accept(listend,(struct sockaddr*)&client,&len);//等待客户端连接
		
		if (-1==connectd)
		{
			perror("create connect socket error\n");
			continue;
		}
		printf("connect  with %s:%d\n",inet_ntoa(client.sin_addr),htons(client.sin_port));
		
		while(1){
				memset(send_buf,0,2048);
				memset(recv_buf,0,2048);
				
				//5. recv from and send to client
				recvnum = recv(connectd,recv_buf,sizeof(recv_buf),0);
				if (0>recvnum)
				{
					perror("recv error\n");
					close(connectd);
					break;
				}
				if (0==recvnum)
				{
					perror("the client quit abnormally\n");
					close(connectd);
					break;
				}
				
				recv_buf[recvnum]='\0';
				printf("rms>>>%s\n",recv_buf);

				if (0==strcmp(recv_buf,"quit"))
				{
					perror("the client quit\n");
					close(connectd);
					break;
				}

				//execute cmd
				strcpy(cmd,"/bin/");
				strcat(cmd,recv_buf);
				execute(cmd,send_buf);


				if ('\0'==*send_buf)
				{
					memset(cmd,0,sizeof(cmd));
					strcpy(cmd,"/sbin/");
					strcat(cmd,recv_buf);
					execute(cmd,send_buf);
					
					if ('\0'==*send_buf)
					{	
						memset(cmd,0,sizeof(cmd));
						strcpy(cmd,"/usr/bin/");
						strcat(cmd,recv_buf);
						execute(cmd,send_buf);
					}
					
					if ('\0'==*send_buf)
					{	
						memset(cmd,0,sizeof(cmd));
						strcpy(cmd,"/usr/sbin/");
						strcat(cmd,recv_buf);
						execute(cmd,send_buf);
					}
				}
				if ('\0'==*send_buf)
				{
					sprintf(send_buf,"command is not vaild,check it please\n");
				}
				
				printf("%s\n",send_buf);
				if ( 0 >send(connectd,send_buf,sizeof(send_buf),0)) 
				{
					perror("send error\n");
					close(connectd);
					break;
				}
			}

			printf("disconnect with %s:%d\n",inet_ntoa(client.sin_addr),htons(client.sin_port));
   }


	close(listend);
	return 0;

}

//execute cmd
int execute(char* command,char* buf)
{
	FILE * 	fp;
	int count;

	if (NULL==(fp = popen(command,"r")))
	{
		perror("creating pipe error\n");
		exit(1);
	}
	
	count = 0 ;

	while(((buf[count] = fgetc(fp))!=EOF)&&count<2047)
	count++;
	buf[count]='\0';

	pclose(fp);
	return count;

}


server端(多线程版)

server可同时连接2个clinet进行通信


#include<stdlib.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netdb.h>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>	//线程库

#define PORT 8900

int execute(char* cmd,int connectd)
{
    char buf[2048];
    FILE* fp;
    char* errbuf="command cannot execute\n";
    int ret;
    int counter;

    fp=NULL;
    counter=0;
    memset(buf,0,2048);

    if ((fp = popen(cmd, "r")) == NULL)
    {
        perror("open failed!");
		ret=send(connectd,errbuf,strlen(errbuf),0);
        // ret=sendto(sockfd,errbuf,strlen(errbuf),0,(struct sockaddr*)&client,sizeof(struct sockaddr));
        return -1;
    }

    while((!feof(fp))&&(counter<2048))
    {
        buf[counter]=fgetc(fp);
        counter++;     
    }
	ret=send(connectd,buf,strlen(buf),0);
    if(0>ret)
        return -1;

    return 0;
}


// 子线程,完成服务端与某一个客户端的持续通信
//child thread
//enable server to complete constant communication with another client
void* workThread(void *arg){
	int connectd = *(int*)arg;	
	int recvnum;
	char recv_buf[2048];
    while(1)
    {
        memset(recv_buf,'\0',2048);
        if (0>(recvnum = recv(connectd,recv_buf,sizeof(recv_buf),0)))
        {
            perror("recv error\n");
            break;
        }
        printf("recv cmd is %s\n", recv_buf);
        // 消息中传输了回车符,会影响strcmp结果
        recv_buf[recvnum] = '\0';
        if (0==strcmp(recv_buf,"quit"))
        {	
            printf("server is terminated by client\n");
            close(connectd);
            break;
        }
        else
        {
            execute(recv_buf,connectd);
        }    
    }
	pthread_exit(NULL);
}



int main(int argc,char** argv)
{
	struct sockaddr_in server;
	struct sockaddr_in client;
	int len;
	int port;
	int listend;
	int connectd;
	int sendnum;
	int opt;
	int recvnum;
	char send_buf[2048];
	char recv_buf[2048];

	port= PORT;
	memset(send_buf,0,2048);
	memset(recv_buf,0,2048);
	
    opt = SO_REUSEADDR;
      
    // 1.create socket 
    if (-1==(listend=socket(AF_INET,SOCK_STREAM,0)))
    {
        perror("create listen socket error\n");
        exit(1);
    }
    setsockopt(listend,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

    #ifdef DEBUG
        printf("the listen id is %d\n",listend);
    #endif

    memset(&server,0,sizeof(struct sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(port);

    //bind addr and port
    // 套接字,服务端信息绑定,接收信息的地址。两个监听套接字和连接套接字是为了并发操作。
    // 2.bind
    if (-1==bind(listend,(struct sockaddr *)&server,sizeof(struct sockaddr)))
    {
	    perror("bind error\n");
	    exit(1);
    }

    //listen
    //  5 是并发个数
    // 3.listen
    if (-1==listen(listend,5))
    {
	    perror("listen error\n");
	    exit(1);
    }

    // main主线程,负责监听连接请求和新建消息传输线程
    while (1)
    {
        //accept
    	//  连接套接字,后两个参数,客户端ip地址和长度。是通过三次握手从客户端接收。长度参数一定要初始化
        // 4. accept
	    if (-1==(connectd=accept(listend,(struct sockaddr*)&client,&len)))
	    {
            perror("create connect socket error\n");
            continue;
	    }
        
	    // 创建一个新线程专门处理与某一个客户端的通信
	    pthread_t tid;
	    if(0 != pthread_create(&tid, NULL, workThread, &connectd))
	    {
	    	printf("create thread fail\n");
	    	continue;
	    } 
	    printf("new client!\n");
   }
    fprintf(stderr,"server is down\n");
    close(listend);
    return 0;
}

client端

#include<stdlib.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netdb.h>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>


void print_usage(char * cmd)
{
	fprintf(stderr," %s usage:\n",cmd);
	fprintf(stderr,"%s IP_Addr [port]\n",cmd);
}

int main(int argc,char** argv)
{
	struct sockaddr_in server;
	int ret;
	int len;
	int port;
	int sockfd;
	int sendnum;
	int recvnum;
	char send_buf[2048];
	char recv_buf[2048];

	if ((2>argc)|| (argc >3))
	{
		print_usage(argv[0]);
		exit(1);

	}
	if (3==argc) 
	{
		port = atoi(argv[2]);
	}
	
	//create socket
	sockfd=socket(AF_INET,SOCK_STREAM,0);
	if (-1==sockfd)
	{
		perror("create socket error\n");
		exit(1);
	}

	memset(&server,0,sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = inet_addr(argv[1]);
	server.sin_port = htons(port);
	
	//connect
	ret=connect(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr));
	if (0 > ret)
	{
		perror("connect error");
		close(sockfd);
		exit(1);
	}
	
	//send to and recv from
	while(1){
		memset(send_buf,0,2048);
		memset(recv_buf,0,2048);

		printf("rms>>>");
		scanf("%s",send_buf);
		len=send(sockfd,send_buf,strlen(send_buf),0);
		if (0 > len)
		{
			perror("send data error\n");
			close(sockfd);
			exit(1);
		}
		
		if (0==strcmp(send_buf,"quit"))
		{
			perror("remote control terminate\n");
			break;
		}

		if (0>(len=recv(sockfd,recv_buf,2048,0)))
		{
			perror("recv data error\n");
			close(sockfd);
			exit(1);
		}

		recv_buf[len]='\0';
		printf("%s\n",recv_buf);

	}
	
	close(sockfd);
	return 0;
	
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值