FTP客户端:连接重置,在应用程序退出之前无法关闭连接

时间:2017-03-11 04:58:28

标签: c++ tcp ftp-client

概述

在使用标准套接字API的Fedora 24 x86_64上的c ++(gcc-c ++ 6.3.1)中,我基于RFC-959的少数几个组件创建了一个基本的FTP客户端。我遇到了一个偶然的问题,当接收或发送数据到服务器时,数据连接被重置。我可以毫不费力地关闭套接字并在数据读取的情况下继续执行,但是在执行写操作时我的程序非常认真(例如使用put / STOR)。

到目前为止,该程序中有很多代码,因此我将在答案中包含最相关的部分,并尝试抽象其余部分。如果需要额外的代码段,我将根据请求添加它们。

详细流程

假设控制连接已经起作用并且用户已通过身份验证。

  1. 我将被动模式查询到服务器(PASV)。
  2. 我接受被动回应(227)。
  3. 我根据响应的IP和端口号打开数据连接。
  4. 我向服务器查询商店请求(STOR
  5. 我收到商店批准(150)
  6. 我第一次调用send(),发送一些数据,但返回-1。
  7. 验证errno值等于ECONNRESET
  8. 我尝试关闭套接字
  9. 我从服务器(226)
  10. 读取了确认的控制连接

    观察

    当尝试在上面的步骤8中关闭连接时,我尝试了一些不同的东西。

    shutdown(fileDescriptor, [any flag]) 返回-1,ENOTCONN / 107,传输端点未连接。

    close(fileDescriptor)返回0表示成功(偶尔我也看到ECONNRESET)。

    SO_LINGER设置为立即关闭时,此行为不会更改。事实上,最有趣的部分是服务器向我发送Rst数据包后,我的客户端永远不会发送自己的RstFin,直到我终止该程序。

    启用TCP_NODELAY以禁用Nagle的算法并不会改变任何内容。

    数据包监视:标准FTP客户端

    这是观察大多数unix操作系统附带的标准FTP客户端上传输的数据包。

    Packet         Direction  Purpose
    ftp: PASV      -->        Client prompt for passive mode
    ftp: 227       <--        Server approve passive mode
      tcp: Syn     -->        Client initiate handshake for data connection
      tcp: Syn+Ack <--        Server acknowledge handshake
      tcp: Ack     -->        Client acknowledge acknowledgement
    ftp: STOR      -->        Client prompt to store file
    ftp: 150       <--        Server approve of store request
      tcp: Rst+Ack <--        Server warns that connection is closed/reset
      tcp: Fin+Ack -->        Client closes connection
      tcp: Ack     -->        Client acknowledges server
    ftp: 226       <--        Server sends response that file upload done
    

    我的客户的差异

    如果您从我的客户端观察到相同的事务,则在调用FinAck时,永远不会发送Rst + close()shutdown()个数据包。

    此数据连接无法关闭后,控制连接拒绝再发送任何响应,这会导致将来所有命令挂起。但是一旦我关闭程序,就会在所有打开的连接上发送重置,并关闭连接。

    有没有人知道我在尝试终止数据连接时遇到的任何明显麻烦?为什么不关闭()或关闭()实际关闭套接字,如何在成功之前强制它不返回?

0 个答案:

没有答案