⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myftpclient.c

📁 简单ftp协议实现
💻 C
字号:
#include "common.h"#define LOCAL_IP "192.168.0.74"struct client_state{  int isCmdConnected;  int isTsfConnected;  short server_port;  unsigned int server_addr;};int csock;int dlsock;int dtsock;struct sockaddr_in server_cmd_addr;struct sockaddr_in serverdl;struct sockaddr_in serverdt;struct client_state cs;int get_command( char * buf, int buflen){  printf("\033[1;32mfancy ftp>\033[m");  int h;  h = getline(&buf, &buflen, stdin);  buf[h-1] = '\0';  return( strlen(buf));}int parse_command(char *cmd){  int len = strlen(cmd);  int end;  end = 0;  while (end<len && cmd[end]!=' ')    {      cmd[end] = toupper(cmd[end]);      end++;    }  if (end == 0)    return 0;  else if (strncmp(cmd,"LS",end)==0 || strncmp(cmd, "DIR", end)==0)    return 1;  else if (strncmp(cmd, "CD", end)==0)    return 2;  else if (strncmp(cmd, "QUIT", end)==0)    return 3;  else if (strncmp(cmd, "GET", end)==0)    return 4;  else if (strncmp(cmd, "PUT", end)==0)    return 5;  else if (strncmp(cmd, "NOOP", end)==0)    return 6;  else if (strncmp(cmd, "PWD", end)==0)    return 7;  else if (strncmp(cmd, "OPEN", end)==0)    return 8;  else if (strncmp(cmd, "CLOSE", end)==0)    return 9;  else if (strncmp(cmd, "HELP", end)==0 || strncmp(cmd, "?", end)==0)    return 10;  else if (strncmp(cmd, "LLS", end)==0)    return 11;  else return 0;}			void * accept_data_connection(void * arg){  int addrlen = sizeof(serverdt);  //  struct sockaddr_in temp;  dtsock = accept(dlsock, (struct sockaddr *) &serverdt, &addrlen);  check_error(dtsock, "accept");}void handle_port_cmd(){  int h;  dlsock = socket(AF_INET, SOCK_STREAM, 0);  int opt = 1;  h = setsockopt(dlsock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));  check_error(h, "setsockopt of data listen socket");  //serverdl.sin_family = AF_INET;  // serverdl.sin_addr.s_addr = htonl(INADDR_ANY);  //serverdl.sin_port = htons(current_data_port++);  int addrlen = sizeof(serverdl);  h = getsockname(dlsock, (struct sockaddr*)&serverdl, &addrlen);  check_error(h ,"getsockname");  serverdl.sin_family = AF_INET;  inet_aton(LOCAL_IP, &(serverdl.sin_addr));  //  serverdl.sin_addr.s_addr = htonl(INADDR_ANY);  unsigned short listenport = LISTEN_PORT;  do     {      serverdl.sin_port = htons( listenport ++);    }  while (bind(dlsock, (struct sockaddr*)&serverdl, sizeof(serverdl))<0);  h = listen(dlsock,10);  check_error(h, "listen");  pthread_t accept_thread;  pthread_create(&accept_thread, NULL, accept_data_connection, NULL);  char cmd_buff[TELNET_LENGTH];  unsigned long dl_ip;  inet_aton(LOCAL_IP,(struct in_addr *) &(dl_ip));  unsigned short dl_port = serverdl.sin_port;  sprintf(cmd_buff, "PORT %d,%d,%d,%d,%d,%d",	  (dl_ip&0xFF), (dl_ip&0x0000FF00)>>8, (dl_ip&0x00FF0000)>>16, dl_ip>>24,	  dl_port&0xFF,dl_port>>8);  send_command(cmd_buff, csock);  printf("[Fancy FTP]%s\n", cmd_buff);   //ss.isPassive = 1;  // h = pthread_join(accept_thread, NULL);  check_error(h, "pthread_join");  receive_reply(cmd_buff,TELNET_LENGTH,csock);  printf("[Fancy FTP]Establish data transfer connection from  through PORT\n");}void get_port(char *arg){  int a[6];  sscanf(arg, "%d,%d,%d,%d,%d,%d", a, a+1, a+2, a+3, a+4, a+5);  cs.server_port = (short)((a[4])+(a[5]<<8));  cs.server_addr = (unsigned long)((a[0])+(a[1]<<8)+(a[2]<<16)+(a[3]<<24));  printf("[Fancy FTP]Server data translation address is %s:%d\n",	 inet_ntoa(cs.server_addr), ntohs(cs.server_port));}void establish_data_connection(){  char buff1[TELNET_LENGTH];  char buff2[TELNET_LENGTH];  strcpy(buff1,"PASV");  send_command(buff1, csock);  receive_reply(buff1, TELNET_LENGTH, csock);  if (strncmp(buff1, "227", 3)!=0)    {      puts("Server not support passive mode.\nUse PORT Command Instead.");      handle_port_cmd();      // return;    }  else    {      char *p1, *p2;      p1 = strchr(buff1,'(');      p2 = strrchr(buff1, ')');      strncpy(buff2, p1+1, p2-p1+1);      get_port(buff2);	      int h;      dtsock = socket(AF_INET, SOCK_STREAM, 0);      check_error(dtsock, "socket of transfer");      serverdt.sin_family = AF_INET;      serverdt.sin_port = cs.server_port;      serverdt.sin_addr.s_addr = cs.server_addr;      h = connect(dtsock, (struct sockaddr*)&serverdt, sizeof(serverdt));      check_error(h, "connect data address");      printf("[Fancy FTP]Establish data connect to %s:%d\n",	     inet_ntoa(serverdt.sin_addr.s_addr), ntohs(serverdt.sin_port));    }}void list_dir(char *arg){  if (!cs.isCmdConnected)    {      puts("Not Connected.");      return;    }  char buff1[TELNET_LENGTH];  //establish_data_connection();  handle_port_cmd();  strcpy(buff1, "LIST");  if (arg[0]!='\0')    {      strcat(buff1, " ");      strcat(buff1, arg);    }  send_command(buff1, csock);  receive_reply(buff1, TELNET_LENGTH, csock);  if (buff1[0]=='1')    {      receive_data(dtsock);    }    close(dtsock);  receive_reply(buff1, TELNET_LENGTH, csock);	}void retr_file(char *arg){  if (!cs.isCmdConnected)    {      puts("Not Connected.");      return;    }  char buff1[TELNET_LENGTH];  char rpy_buff[TELNET_LENGTH];	  strcpy(buff1, "TYPE A");  send_command(buff1, csock);  receive_reply(buff1, TELNET_LENGTH, csock);  establish_data_connection();  sprintf(buff1, "RETR %s", arg);  send_command(buff1, csock);  printf("[Fancy FTP]Get file: %s\n", arg);  receive_reply(buff1, TELNET_LENGTH, csock);  if (buff1[0]=='1')    {      FILE *fl;      fl = fopen(arg, "w");      receive_file(fl, dtsock);      fclose(fl);      close(dtsock);      receive_reply(buff1, TELNET_LENGTH, csock);    }  else    close(dtsock);}void stor_file(char *arg){  if(!cs.isCmdConnected)    {      puts("Not Connected.");      return;    }  FILE *fl;  fl = fopen(arg, "r");  if(fl == 0)    {      puts("File not found.");      return;    }  char buff1[TELNET_LENGTH];  char rpy_buff[TELNET_LENGTH];  strcpy(buff1, "TYPE A");  send_command(buff1, csock);  receive_reply(buff1, TELNET_LENGTH, csock);  establish_data_connection();  sprintf(buff1, "STOR %s", arg);  send_command(buff1, csock);  printf("[Fancy FTP]Put file: %s\n", arg);  receive_reply(buff1, TELNET_LENGTH, csock);  if(buff1[0] == '1')    {      send_file(fl, dtsock);      close(dtsock);      receive_reply(buff1, TELNET_LENGTH, csock);    }  else    close(dtsock);  fclose(fl);}void list_local(){  struct dirent **eps;  int n;  char line_buff[TELNET_LENGTH];  n = scandir("./", &eps, one, alphasort);  if (n >= 0)    {      int cnt;      struct stat s;      for (cnt = 0; cnt < n; ++cnt)	{	  strcpy(line_buff, eps[cnt]->d_name);	  stat(line_buff, &s);	  char pbuff[32];	  if (!S_ISREG(s.st_mode) && !S_ISDIR(s.st_mode)) continue;	  permission(s.st_mode, pbuff);	  struct passwd *uinfo;	  struct group *ginfo;	  uinfo = getpwuid(s.st_uid);	  ginfo = getgrgid(s.st_gid);				  char tbuff[256];	  struct tm* t;	  t = localtime(&s.st_mtime);	  strftime(tbuff, 1024, "%b %d %k:%M", t);	  sprintf(line_buff, "%s%3d %s    %s      %12d %s %s\r\n",		  pbuff, s.st_nlink,		  uinfo->pw_name, ginfo->gr_name,		  s.st_size, tbuff,		  eps[cnt]->d_name);	  printf("%s", line_buff);	}    }  else    perror ("Couldn't open the directory");}int parse_server_addr(char * arg, char * user, char * pass){  char *p1, *p2, *p3;  p1 = strchr(arg, '@');  int flag = 1;  if (p1!=NULL)    {      p2 = strchr(arg, ':');      if (p2>p1) flag = 0;      else	{	  strncpy(user, arg, p2-arg);	  user[p2-arg] = '\0';	  strncpy(pass, p2+1, p1-p2-1);	  pass[p1-p2-1] = '\0';	}      p1++;    }  else p1 = arg;  p2 = strchr(p1, ':');  char tmp[TELNET_LENGTH];  if (flag)    {      if (p2==NULL)	{	  printf("%s\n",p1);	  if (inet_aton(p1, &server_cmd_addr.sin_addr)==0) flag=0;	  server_cmd_addr.sin_port = htons(21);	}      else	{	  strncpy(tmp, p1, p2-p1);	  tmp[p2-p1] = '\0';	  printf("%s\n", tmp);	  if (inet_aton(tmp, &server_cmd_addr.sin_addr)==0)	    {	      flag = 0;	    }	  server_cmd_addr.sin_port = htons(atoi(p2+1));	}      printf("[Fancy FTP]Server address %s:%d\n",	     inet_ntoa(server_cmd_addr.sin_addr.s_addr),	     ntohs(server_cmd_addr.sin_port));    }  if (flag==0)    {      printf("[Fancy FTP]Error, usage: open [user:pass@]host[:port] with correct address!\n");      return -1;    }	  server_cmd_addr.sin_family = AF_INET;  return 0;}void open_cmd_connection(char *arg){  char user[64] = "", pass[64] = "";  char tmp[TELNET_LENGTH];  int h;  h = parse_server_addr(arg, user, pass);  if(h<0)    {      puts( "parse server addr");      return;    }  csock = socket(PF_INET, SOCK_STREAM, 0);  h = connect(csock, (struct sockaddr*)&server_cmd_addr, sizeof(server_cmd_addr));  receive_reply(tmp, TELNET_LENGTH, csock);  if (h<0)    {      printf("Connection Refused.\n");      cs.isCmdConnected = 0;      return;    }  int t;  if (user[0]=='\0')    {      printf("User:");      t = 64;      fgets(user, 64, stdin);      int len =  strlen(user);      user[len-1] = '\0';    }  if (pass[0]=='\0')    {      printf("Pass:");      t = 64;      fgets(pass, 64, stdin);      int len = strlen(pass);      pass[len-1] = '\0';    }  printf("[Fancy FTP]user<%s> pass<%s>\n", user, pass);  sprintf(tmp, "USER %s", user);  send_command(tmp, csock);  receive_reply(tmp, TELNET_LENGTH ,csock);  sprintf(tmp, "PASS %s", pass);  send_command(tmp, csock);  receive_reply(tmp, TELNET_LENGTH, csock);  if (tmp[0]=='2')    {      cs.isCmdConnected = 1;    }  else cs.isCmdConnected = 0;}void user_pi(){  char cmd_buff[TELNET_LENGTH];  char rpy_buff[TELNET_LENGTH];  char param_buff[TELNET_LENGTH];  char *para;  while (1)    {      int len = get_command(cmd_buff, TELNET_LENGTH);      int cmd_id = parse_command(cmd_buff);      printf("[Fancy FTP]Receive command: <%s>(%d)\n", cmd_buff, cmd_id);      switch (cmd_id)	{	case 0: puts("\033[1;31mError: Command not recognized\033[m"); break; //Syntax error	case 1: //ls, dir	  parse_parameters(cmd_buff, 1, param_buff);	  list_dir(param_buff);	  break;	case 2: //cd	  if (!cs.isCmdConnected) {puts("Not connected."); break;}	  parse_parameters(cmd_buff, 1 ,param_buff);	  if (strcmp(param_buff,"..")==0) strcpy(cmd_buff,"CDUP");	  else sprintf(cmd_buff,"CWD %s", param_buff);	  send_command(cmd_buff, csock);	  receive_reply(rpy_buff, TELNET_LENGTH, csock);	  break;	case 3:  //quit	  if (cs.isCmdConnected)	    {	      sprintf(cmd_buff, "QUIT");	      send_command(cmd_buff, csock);	      receive_reply(rpy_buff, TELNET_LENGTH, csock);	      close(csock);	      cs.isCmdConnected = 0;	    }	  break;	case 4: //get	  if (!cs.isCmdConnected) {puts("Not connected."); break;}	  parse_parameters(cmd_buff, 1, param_buff);	  retr_file(param_buff);	  break;	case 5: //put	  if (!cs.isCmdConnected) {puts("Not connected."); break;}	  parse_parameters(cmd_buff, 1, param_buff);	  stor_file(param_buff);				  break;	case 6: //noop	  if (!cs.isCmdConnected) {puts("Not connected."); break;}	  strcpy(cmd_buff, "NOOP");	  send_command(cmd_buff, csock);	  receive_reply(rpy_buff, TELNET_LENGTH, csock);	  break;	case 7: //pwd	  if (!cs.isCmdConnected) {puts("Not connected."); break;}	  strcpy(cmd_buff, "PWD");	  send_command(cmd_buff, csock);	  receive_reply(rpy_buff, TELNET_LENGTH, csock);	  break;	case 8: //open	  if(!cs.isCmdConnected)	    {	      parse_parameters(cmd_buff, 1, param_buff);	      open_cmd_connection(param_buff);	    }	  else	    {	      puts("\033[1;31mError: Already Connected to An FTP Server\033[m"); 	    }	  break;	case 9: //close	  if(cs.isCmdConnected)	    {	      sprintf(cmd_buff, "QUIT");	      send_command(cmd_buff, csock);	      receive_reply(rpy_buff, TELNET_LENGTH, csock);	      close(csock);	      cs.isCmdConnected = 0;	    }	  else 	    {	      puts("Not connected.");	    }	  break;	case 10: //help && ?	  printf("Support Commands:\nopen   cd    quit    close\npwd    noop    ls    lls\nhelp\n");	  if (!cs.isCmdConnected) {break;}	  strcpy(cmd_buff, "HELP");	  send_command(cmd_buff, csock);	  receive_reply(rpy_buff, TELNET_LENGTH, csock);	  break;	case 11: //lls	  list_local();	  break;	}      if (cmd_id==3) break;    }  close(csock);}int main(int argc, char * argv[]){  if(argc == 2)    {      open_cmd_connection(argv[1]);    }  user_pi();  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -