2017-05-11 28 views
0

私は学校のプロジェクト用に単純なFTPサーバーをコーディングしています。ファイル転送に問題があります。TCPソケットがなぜブロックされているのですか?

実際、コマンドPASVが送信されると、指定されたポートでソケットを作成してリッスンしますが、その後、コマンドRETRが送信され、ソケットファイル記述子にファイルを書き込もうとすると、プログラムとftpクライアントの終了を待つ。

はなぜこの書き込みをブロックしていますか?

この関数は、私のソケットこの機能オープン広告は、データラインthroughtファイルを送信

void     cmd_pasv(t_handle *hdl)             
{                        
    struct sockaddr_in data_sock;                
    uint16_t    port;                 
    socklen_t    len;                 

    len = sizeof(data_sock);                  
    if ((hdl->data_fd = create_s_socket(&data_sock, 0)) != -1)         
    {                       
     listen(hdl->data_fd, 5);                 
     getsockname(hdl->data_fd, (struct sockaddr *)&data_sock, &len);       
     port = ntohs(data_sock.sin_port);               
     printf("port = %d\n", port);                
     set_rep(hdl, 227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d).",       
       (int)(data_sock.sin_addr.s_addr & 0xFF),           
       (int)((data_sock.sin_addr.s_addr & 0xFF00) >> 8),         
       (int)((data_sock.sin_addr.s_addr & 0xFF0000) >> 16),        
       (int)((data_sock.sin_addr.s_addr & 0xFF000000) >> 24),       
       (int)(port/256), (int)(port % 256));           
     printf("data fd %d\n", hdl->data_fd);              
    }                       
    else                       
    set_rep(hdl, 500, "Canno open data connection");           
} 

int  create_s_socket(struct sockaddr_in *sock, int port)          
{                        
    int   socket_fd;                  
    int   enable;                   

    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)          
    return (-1);                    
    enable = 1;                     
    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)    
    return (-1);                    
    sock->sin_family = AF_INET;                 
    sock->sin_addr.s_addr = htonl(INADDR_LOOPBACK);            
    sock->sin_port = htons(port);                 
    if (bind(socket_fd, (struct sockaddr *)sock, sizeof(*sock)) < 0)        
    return (-1);                    
    return (socket_fd);                   
} 

この機能は、オープンデータ接続を開く(パッシブモード)を作成

void   cmd_retr(t_handle *hdl)               
{                        
    char   *fullpath;                  
    FILE   *file;                   
    size_t  nread;                   
    char   buf[BLOCK_SIZE];                

    log_msg(INFO, "data fd is %d", hdl->data_fd);             
    if (hdl->data_fd > 0)                   
    {                       
     log_msg(INFO, "data fd is %d", hdl->data_fd);            
     if (hdl->cmd_arg)                   
     {                      
      log_msg(INFO, "file to uploadis %s", hdl->cmd_arg);         
      fullpath = malloc(sizeof(char) *              
          strlen(hdl->path) + strlen(hdl->cmd_arg) + 2);      
      sprintf(fullpath, "%s/%s", hdl->path, hdl->cmd_arg);         
      log_msg(INFO, "full path is %s", fullpath);           
      if ((file = fopen(fullpath, "r")) != NULL)           
      {                     
       log_msg(INFO, "file opened correctly");           
       while ((nread = fread(buf, sizeof(char), BLOCK_SIZE, file)) > 0)     
       {                    
        log_msg(INFO, "read %d bytes \"%s\"", nread, buf);       
        if (write(hdl->data_fd, buf, nread) == -1)         
        log_msg(ERROR, "write: %s", strerror(errno));        
       }                    
       if (nread < 0)                 
       log_msg(ERROR, "read: %s", strerror(errno));         
      }                     
      else                     
      set_rep(hdl, 000, "File \"%s\" not found", fullpath);        
      free(fullpath);                  
     }                      
     else                      
     set_rep(hdl, 000, "Missing arg");              
    }                       
    else                       
    set_rep(hdl, 000, "Data connection not open fd %d", hdl->data_fd);       
}    

感謝;)

答えて

1

実際には、コマンドPASVが送信されると、 指定ポートのソケットを作成してリッスンしますが、その後、コマンドRETRが に送信され、ファイルをソケットファイル記述子に書き込もうとすると、 プログラムの実行をブロックし、ftpクライアントは待機し続けます。

はなぜこの書き込みをブロックしていますか?

すべての関連コードを提示したかどうかは不明です。もしあなたが持っていれば、問題は確かにあなたがサーバーソケットに書き込もうとしていることです。代わりにaccept()そのソケットへの接続、それは予想クライアントからのものであることを確認し、通信する(別のファイル記述子を持つことになります)その結果接続ソケットを使用する必要があります。私のコードで「cmd_pasv」機能は、ちょうどその要求としたクライアントのIPアドレスとポートを読み込み、保存する必要がありますので、

+0

、ときに、クライアントの要求それは作成するには、このprevioulsy格納されているIPとポートの組み合わせを使用したファイルソケットは受け入れてから書き込みますか? –

+1

@ TheChampionの場合、サーバーはまずPASVコマンドを受け入れ、クライアントに適切な応答を送信する必要があります。データ・チャネルは、*セッションごとの*プロパティである、しかし、ないファイル単位または要求財産ので、あなたは、クライアントがデータチャネルを開こうとする前に、新しいコマンドを発行することを期待すべきではない、と確かに開きませんコマンドごとの新しい接続。適切なサーバー側の動作をどのように実装するかは、あなた次第です。この回答のポイントは、接続されているソケットではなくリッスンソケットに書き込もうとすると発生する問題です。 –

関連する問題