简体   繁体   English

写在TCP套接字阻塞为什么?

[英]Write on tcp socket blocking why?

I'm coding simple FTP server for a school project and I have a problem with file transfer. 我正在为学校项目编码简单的FTP服务器,但是文件传输存在问题。

In fact, when the command PASV is sent, I create a socket with the specified port and listen but then later when the command RETR is sent and I try to write the file on the socket file descriptor, the write block the excecution of the program and the ftp client keep waiting. 实际上,当发送命令PASV时,我创建了一个具有指定端口的套接字并进行侦听,但是随后在发送命令RETR时,我尝试将文件写入套接字文件描述符中,该写入会阻止程序的执行和ftp客户端保持等待状态。

Why is this write blocking ? 为什么写阻塞?

This function create my socket 这个函数创建我的套接字

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

This function open open the data connection (passive mode) 此功能打开打开数据连接(被动模式)

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

This function open ad send the file throught the data line 此功能打开广告通过数据行发送文件

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

Thanks ;) 谢谢 ;)

In fact, when the command PASV is sent, I create a socket with the specified port and listen but then later when the command RETR is sent and I try to write the file on the socket file descriptor, the write block the excecution of the program and the ftp client keep waiting. 实际上,当发送命令PASV时,我创建了一个具有指定端口的套接字并进行侦听,但是随后在发送命令RETR时,我尝试将文件写入套接字文件描述符中,该写入会阻止程序的执行和ftp客户端保持等待状态。

Why is this write blocking ? 为什么写阻塞?

It's unclear whether you've presented all the relevant code. 目前尚不清楚您是否已提供所有相关代码。 If you have, then the problem is certainly that you are trying to write to the server socket. 如果有,那么问题肯定出在您正在尝试写入服务器套接字。 You should instead accept() a connection to that socket, verify that it is from the expected client, and use the resulting connected socket (which will have a different file descriptor) to communicate. 您应该改为accept()与该套接字的连接,验证它是否来自预期的客户端,并使用生成的连接套接字(它将具有不同的文件描述符)进行通信。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM