Linux下用socket实现远程执行命令

服务器端程序:

/**********************************************************
 * server.c
 * 服务器端程序
 *
 *********************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#define BUFSIZE 8192
#define DEFAULT_PORT 5320

enum{CMD_NAME,SRC_PORT};

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

int main(int argc,char *argv[])
{
  struct sockaddr_in server; //服务器地址
  struct sockaddr_in client; //客户机地址
  int len; //sockaddr_in的长度
  int port; //服务器端口号
  int s; //接收报文用描述符
  int s0; //接收连接用描述符
  int cn; //接收命令的字数
  int sn; //发送报文的字节数
  int rn; //接收报文的字节数
  char cmd1[BUFSIZE]; //第一个语句命令
  char cmd2[BUFSIZE]; //第二个语句命令
  char recv_buf[BUFSIZE]; //接收缓冲区
  char send_buf[BUFSIZE]; //发送缓冲区
  
  //实际参数的处理(端口号)
  if(argc==2){
    if((port=atoi(argv[SRC_PORT]))==0){
      struct servent *se; //服务信息
      
      if((se=getservbyname(argv[SRC_PORT],"tcp"))!=NULL)
        port=(int) ntohs((u_short)se->s_port);
      else{
        fprintf(stderr,"getservbyname error\n");
 exit(EXIT_FAILURE);
      }
    }
  }else
    port=DEFAULT_PORT;
      
    //使用TCP协议打开一个套接字
  if((s0=socket(AF_INET,SOCK_STREAM,0))<0){
    perror("socket");
    exit(EXIT_FAILURE);
  }
    
  //设定服务器地址
  memset((char *)&server,0,sizeof(server));
  server.sin_family=AF_INET;
  server.sin_addr.s_addr=htonl(INADDR_ANY);
  server.sin_port=htons(port);
  if(bind(s0,(struct sockaddr *)&server,sizeof(server))<0){
    perror("bind");
    exit(EXIT_FAILURE);
  }
    
  //开始接受建立连接请求
  listen(s0,5);
    
  //接收连接循环
  while(1){
  //接收连接处理
    len=sizeof(client);
    if((s=accept(s0,(struct sockaddr *)&client,&len))<0){
      perror("accept");
      exit(EXIT_FAILURE);
    }
    printf("Connected From '%s'\n",inet_ntoa(client.sin_addr));
      
#ifdef FORK_SERVER
  if(fork()!=0){
    close(s);
    continue;
  }
  close(s0);
#endif
    //服务器处理的主要子程序
    while(1){
      int i=0; //接收字符的计数器
    
      sn=sprintf(send_buf,"TCP>");
      send(s,send_buf,sn,0);
    
      receive: //流型数据的接收处理
      if((rn=recv(s,&recv_buf[i],1,0))<0)
        break;
      
      //以换行为单位进行接收处理
      if(recv_buf[i]!='\n'){
        i++;
        if(i<BUFSIZE-1)
          goto receive;
      }
      recv_buf[i]='\0';
      printf("receive '%s'\n",recv_buf);
   
      //接收命令的处理
      if((cn=sscanf(recv_buf,"%s%s",cmd1,cmd2))<=0)
        continue;
      else if(cn==2 && strcmp(cmd1,"show")==0){
        if(strcmp(cmd2,"route")==0)
#ifdef _linux
  sn=execute("/usr/bin/netstat -rn",send_buf,BUFSIZE);
#else
  sn=execute("/bin/netstat -rn",send_buf,BUFSIZE);
#endif
        else if(strcmp(cmd2,"arp")==0)
#ifdef _linux
  sn=execute("/usr/sbin/arp -an",send_buf,BUFSIZE);
#else
  sn=execute("/sbin/arp -an",send_buf,BUFSIZE);
#endif
          else if(strcmp(cmd2,"tcp")==0)
#ifdef _linux
  sn=execute("/usr/bin/netstat -tn",send_buf,BUFSIZE);
#else
  sn=execute("/bin/netstat -tn",send_buf,BUFSIZE);
#endif
            else if(strcmp(cmd2,"nic")==0)
       sn=execute("/sbin/ifconfig -a",send_buf,BUFSIZE);
     else
       sn=sprintf(send_buf,"parameter error '%s'\n"
                           "show[route|arp|tcp|nic]\n",cmd2);
 }else if(cn==1){
   if(strcmp(cmd1,"quit")==0)
     break;
   send_buf[0]='\0';
   if(strcmp(cmd1,"help")!=0)
     sprintf(send_buf,"command error '%s'\n",cmd1);
   strcat(send_buf,"command:\n"
                   "show route\n"
     "show arp\n"
     "show tcp\n"
     "show nic\n"
     "quit\n"
     "help\n");
   sn=strlen(send_buf);
 }else
   sn=sprintf(send_buf,"command error '%s'\n",cmd1);
 if(sn==0)
   sn=sprintf(send_buf,"\n");
   
 if(send(s,send_buf,sn,0)<0)
   break;
 printf("%s",send_buf);
      }
      printf("Connection closed.\n");
      close(s);
    }
    close(s0);
    
    return EXIT_SUCCESS;
  }
  
  /*
   *int execute(char *command,char *buf,int bufmax);
   *
   *功能
   * 执行命令,将结果存储到缓冲区中
   *实际参数
   * char *command; 所执行的命令
   * char *buf; 存储输出结果的缓冲区
   * int bufmax 缓冲区的大小
   *返回值
   * int 存储到缓冲区的字符数
   */
int execute(char *command,char *buf,int bufmax)
{
  FILE *fp; //文件指针
  int i; //输入数据的字节数
     
  if((fp=popen(command,"r"))==NULL){
    perror(command);
    i=sprintf(buf,"server error: '%s' cannot execute.\n",command);
  }else{
    i=0;
    while((buf[i]=fgetc(fp))!=EOF && i<bufmax-1)
      i++;
  
    pclose(fp);
  }
  return i;
}


以下是客户端程序!

/***************************************************
 * client.c
 * 在Red Hat 9.0 GCC下调试通过!
 * 在运行服务器端程序之后,
 * 再运行客户端,否则,连接会失败!
 * ./client 你的ip地址 [端口]
 * 呵呵!!
 * GoodLuck
 ***************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/socket.h>
#include<sys/time.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#define BUFSIZE 8192
#define DEFAULT_PORT 5320

enum {SMD_NAME,DST_IP,DST_PORT};

int main(int argc,char *argv[])
{
  struct sockaddr_in server;    //服务器地址
  unsigned long dst_ip;         //服务器IP地址
  int port;     //端口号
  int s;        //套接字的描述符
  int n;        //输入数据的字节数
  char buf[BUFSIZE];    //接收缓
  char cmd[BUFSIZE];    //发送缓
  struct timeval tv;    //select超时时间
  fd_set readfd;        //使用select检索出的描述符

  //实际参数的检查
  if(argc!=2 && argc!=3){
    fprintf(stderr,"Usage: %s hostname[port]\n",argv[0]);
    exit(EXIT_FAILURE);
  }
  
  //检索服务器的ip地址
  if((dst_ip=inet_addr(argv[DST_IP]))==INADDR_NONE){
    struct hostent *he;  //主机信息
     
    if((he=gethostbyname(argv[DST_IP]))==NULL){
      fprintf(stderr,"gethostbyname error\n");
      exit(EXIT_FAILURE);
    }
    memcpy((char *)&dst_ip,(char *)he->h_addr,sizeof(he->h_addr));
  }

  //检索服务器的端口号
  if(argc==3){
    if((port=atoi(argv[DST_PORT]))==0){
      struct servent * se; //服务信息
      
      if((se=getservbyname(argv[DST_PORT],"tcp"))!=NULL)
        port=(int) ntohs((u_short)se->s_port);
      else{
        fprintf(stderr,"getservbyname error\n");
        exit(EXIT_FAILURE);
      }
    }
  }else
    port=DEFAULT_PORT;
  
  //使用TCP协议打开一个套接字
  if((s=socket(AF_INET,SOCK_STREAM,0))<0){
    perror("socket");
    exit(EXIT_FAILURE);
  }
  
  //设定服务器的地址,建立一个连接
  memset((char *)&server,0,sizeof(server));
  server.sin_family=AF_INET;
  server.sin_addr.s_addr=dst_ip;
  server.sin_port=htons(port);
  if(connect(s,(struct sockaddr *)&server,sizeof(server))<0){
    perror("connect");
    exit(EXIT_FAILURE);
  }
  
  printf("Connected to '%s'\n",inet_ntoa(server.sin_addr));
  
  //客户机处理的主要子程序
  while(1){
    //select超时的设定
    tv.tv_sec=600;
    tv.tv_usec=0;
    
    //标准输入,有无来自服务器的报文
    FD_ZERO(&readfd);
    FD_SET(0,&readfd);
    FD_SET(s,&readfd);
    if((select(s+1,&readfd,NULL,NULL,&tv))<=0){
      fprintf(stderr,"\nTimeout\n");
      break;
    }
    
    //标准输入
    if(FD_ISSET(0,&readfd)){
      if((n=read(0,buf,BUFSIZE-1))<=0)
        break;
      buf[n]='\n';
      sscanf(buf,"%s",cmd);
      if(strcmp(cmd,"quit")==0)
        break;
      if(send(s,buf,n,0)<=0)
        break;
    }
    
    //服务器
    if(FD_ISSET(s,&readfd)){
      if((n=recv(s,buf,BUFSIZE-1,0))<=0){
        fprintf(stderr,"connection closed.\n");
 exit(EXIT_FAILURE);
      }
      buf[n]='\0';
      printf("%s",buf);
      fflush(stdout);
    }
  }
  
  strcpy(buf,"quit");
  send(s,buf,n,0);
  close(s);
  
  return EXIT_SUCCESS;
}


此文转自:http://blog.chinaunix.net/space.php?uid=405749&do=blog&id=27757,在此表示感谢!


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值