写在tcp socket阻塞为什么?

时间:2017-05-11 20:24:05

标签: c sockets tcp ftp

我正在为学校项目编写简单的FTP服务器,我遇到文件传输问题。

实际上,当发送命令PASV时,我创建一个带有指定端口的套接字并监听但后来当发送命令RETR并且我尝试在套接字文件描述符上写入文件时,写块阻止执行该程序和ftp客户端一直在等待。

为什么这个写阻塞?

此功能创建我的套接字

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_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");                                           
}

此功能打开广告通过数据线发送文件

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 个答案:

答案 0 :(得分:1)

  

实际上,当发送命令PASV时,我创建一个带有的套接字   指定端口和监听,但稍后在发送命令RETR时   我尝试在socket文件描述符上写入文件   阻止程序的执行,ftp客户端一直在等待。

     

为什么这个写阻塞?

目前还不清楚您是否提供了所有相关代码。如果你有,那么问题肯定是你试图写入服务器套接字。您应该accept()与该套接字建立连接,验证它是否来自预期的客户端,并使用生成的连接的套接字(具有不同的文件描述符)进行通信。