初学者ftp服务器困境,部分deux

时间:2015-04-28 01:22:51

标签: c sockets ubuntu server rtp

当我尝试使用ftp访问我的ls命令时,我总是在PORT部分命中425,有人可以告诉我为什么会这样吗?我的用户部分工作,如果我可以让端口工作,我可以专注于STOR和RETR。

/*FTP server*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h> 
/*for getting file size using stat()*/
#include<sys/stat.h>

/*for sendfile()*/
#include<sys/sendfile.h>

/*for O_RDONLY*/
#include<fcntl.h>
int active=0; 
int sock1, sock2;
char buf[100], command[5], filename[20];
struct sockaddr_in remoteaddr, remoteaddr_data;
int main(int argc,char *argv[])
{
  struct sockaddr_in server, client;
  struct stat obj;
  struct sockaddr_in local_data_addr_act;
  int s, s_data, s_data_act;
  s = socket(AF_INET, SOCK_STREAM, 0);
  s_data = socket(AF_INET, SOCK_STREAM, 0);
  s_data_act = socket(AF_INET, SOCK_STREAM, 0);
  int k, i, size, len, c;
  int filehandle;
  sock1 = socket(AF_INET, SOCK_STREAM, 0);
  if(sock1 == -1)
  {
    printf("Socket creation failed");
    exit(1);
  }
  server.sin_port = htons(atoi(argv[1]));
  server.sin_addr.s_addr = 0;
  k = bind(sock1,(struct sockaddr*)&server,sizeof(server));
  if(k == -1)
  {
    printf("Binding error");
    exit(1);
  }
  k = listen(sock1,1);
  if(k == -1)
  {
    printf("Listen failed");
    exit(1);
  }
  len = sizeof(client);
  sock2 = accept(sock1,(struct sockaddr*)&client, &len);
  write(sock2,"220\r\n", 6);
  i = 1;
  while(1)
  {
    recv(sock2, buf, 100, 0);
    printf("%s\n", buf);
    sscanf(buf, "%s", command);
    printf("%s\n", command);
    if(!strcmp(command, "LIST"))
    {
      system("ls >tmp.txt");
      FILE *fin=fopen("tmp.txt","r");
      sprintf(buf, "125\r\n");
      send(sock2, buf, strlen(buf), 0);
      char temp_buf[10];
      while (!feof(fin))
      {
        fgets(temp_buf, 98, fin);
        sprintf(buf, "%s", temp_buf);
        if (!active)send(sock1, buf, strlen(buf), 0);
        else send(s_data_act, buf, strlen(buf), 0); 
      }
      fclose(fin);
      sprintf(buf, "250\r\n");
      send(sock2, buf, strlen(buf), 0);
      if(!active) close(sock1);
      else close(s_data_act);
      sprintf(buf, "226\r\n");
      send(sock2, buf, strlen(buf), 0);
    }
    else if(!strcmp(command,"USER"))
    {
      sprintf(buf, "230\r\n");
      send(sock2, buf, strlen(buf), 0);
    }
    else if(!strcmp(command,"SYST"))
    {
      write(sock2, "502\r\n", 6);
    }
    else if(!strcmp(command,"PORT"))
    {
      unsigned char act_port[2];
      int act_ip[4], port_dec;
      char ip_decimal[40];
      active=1;
      sscanf(command, "PORT %d,%d,%d,%d,%d,%d",&act_ip[0],&act_ip[1],&act_ip[2],&act_ip[3], &act_port[0], &act_port[1]);
      local_data_addr_act.sin_family=AF_INET;
      sprintf(ip_decimal, "%d.%d.%d.%d", act_ip[0], act_ip[1], act_ip[2], act_ip[3]);
      local_data_addr_act.sin_addr.s_addr=inet_addr(ip_decimal);
      port_dec=act_port[0];
      port_dec=port_dec<<8;
      port_dec=port_dec+act_port[1];
      local_data_addr_act.sin_port=htons(port_dec);
      if (connect(s_data_act,(struct sockaddr*)&local_data_addr_act, (int)sizeof(struct sockaddr))!=0)
      {
        printf("%s%d\n",inet_ntoa(local_data_addr_act.sin_addr),ntohs(local_data_addr_act.sin_port)); 
        sprintf(buf, "425\r\n");
        send(sock2, buf, strlen(buf), 0);
        close(s_data_act);
      }
      else
      {
        sprintf(buf, "200\r\n");
        send(sock2, buf, strlen(buf), 0); 
      }
    }
    else if(!strcmp(command,"RETR"))
    {
      sscanf(buf, "%s%s", filename, filename);
      stat(filename, &obj);
      filehandle = open(filename, O_RDONLY);
      size = obj.st_size;
      if(filehandle == -1)
        size = 0;
      send(sock2, &size, sizeof(int), 0);
      if(size)
        sendfile(sock2, filehandle, NULL, size);
    }
    else if(!strcmp(command, "STOR"))
    {
      int c = 0, len;
      char *f;
      sscanf(buf+strlen(command), "%s", filename);
      recv(sock2, &size, sizeof(int), 0);
      i = 1;
      while(1)
      {
        filehandle = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0666);
        if(filehandle == -1)
        {
          sprintf(filename + strlen(filename), "%d", i);
        }
        else
          break;
      }
      f = malloc(size);
      recv(sock2, f, size, 0);
      c = write(filehandle, f, size);
      close(filehandle);
      send(sock2, &c, sizeof(int), 0);
    }
    else if(!strcmp(command, "pwd"))
    {
      system("pwd>temp.txt");
      i = 0;
      FILE*f = fopen("temp.txt","r");
      while(!feof(f))
        buf[i++] = fgetc(f);
      buf[i-1] = '\0';
      fclose(f);
      send(sock2, buf, 100, 0);
    }
    else if(!strcmp(command, "cd"))
    {
      if(chdir(buf+3) == 0)
        c = 1;
      else
        c = 0;
      send(sock2, &c, sizeof(int), 0);
    }
    else if(!strcmp(command, "bye") || !strcmp(command, "QUIT"))
    {
      printf("FTP server quitting..\n");
      i = 1;
      send(sock2, &i, sizeof(int), 0);
      exit(0);
    }
  }
  return 0;
}

1 个答案:

答案 0 :(得分:4)

这段代码充满了错误和错误。无论您尝试使用此代码实现什么,它甚至都不能远离符合要求的FTP服务器实现。

您创建了太多套接字,甚至没有使用所有套接字。你在错误的时间在错误的时间创造了一些它们。

大多数套接字/文件函数调用完全没有错误处理。

没有正确处理套接字读/写,特别是没有考虑TCP是一种流传输的事实,它不能保证写和读之间的1对1关系。你必须要考虑到这一点!

有时将INCORRECT数据写入客户端 - 发送不期望的空终止符,发送数据缓冲区,就好像它们实际上是空终止一样,在不期望的情况下将文件大小发送为二进制整数等等。 / p>

假设接收到的数据在实际上没有终止时为空。

将被动模式数据发送到错误的套接字(甚至没有实现PASV命令开始)。

未正确实施PORTSTORRETR命令(对套接字管理不当)。

未正确实施PWDCDBYE / QUIT命令(发送完全无效的回复)。

而且,虽然技术上不是错误,但你真的不应该使用system()。有更好的本地方式来获取所需的数据。对于LIST,您可以使用opendir()代替,然后根据需要编写目录的条目。对于PWD,您可以使用getcwd()

您需要废弃此代码并重新开始。尝试修复它有太多不妥之处。有关如何正确实现套接字I / O的在线可用的大量示例,尤其是如何使用套接字执行基于行的I / O(因为FTP是基于行的协议)。请阅读RFC 959以了解处理FTP命令/响应和数据传输管理的正确规则