C套接字:write()后跟close()导致数据传输不完整

时间:2014-10-09 03:55:48

标签: c sockets tcp network-programming file-descriptor

我试图编写一个基本的文件服务器,它从客户端获取文件名并通过TCP将数据发送到客户端进行响应。我有一个工作的客户端和服务器应用程序,但我观察了一些奇怪的行为,请考虑以下

    while ((num_read = read (file_fd, file_buffer, sizeof (file_buffer))) > 0)
    {
        if (num_read != write (conn_fd, article_buffer, num_read))
        {
            perror ("write");
            goto out;
        }
    }
    out:
           close(file_fd); close(sub_fd);

file_fd是通过网络发送的文件的文件描述符,conn_fdconnect() ed TCP套接字的文件描述符。

这似乎适用于小文件,但是当我的文件变大(兆字节+)时,文件末尾的某些不一致数据量似乎无法传输。

我怀疑写入后的立即close()语句可能与它有关,所以我在两个sleep()语句之前尝试了1秒close()并且我的客户端成功接收了所有数据。< / p>

有没有比在服务器端执行sleep()更好的方法来处理这个问题?

1 个答案:

答案 0 :(得分:0)

套接字上的成功“写入”并不意味着数据已成功发送到对等方。

如果您使用的是unix派生词,则可以执行“man 7 socket”并检查SO_LINGER“作为潜在的解决方案。

编辑:由于EJP的评论(谢谢),我重读了史蒂文斯关于确保将所有数据传递给同伴的“Unix网络编程”中的主题所说的内容。他说以下(第二版第1卷,第189页):

  

...我们看到当我们关闭连接结束时,根据被调用的函数(关闭或关闭)以及是否设置了SO_LINGER套接字选项,返回可以在三个不同的时间发生。

     
      
  1. close立即返回,完全没有等待(默认值;图7.6)
  2.   
  3. 关闭,直到收到FIN的ACK(图7.7)或
  4.   
  5. shutdown然后读取等待直到我们收到对等的FIN(图7.8)
  6.   

他的数字和他的评论表明除了“应用程序级别确认”之外,shutdown()的组合,后跟read()等待零返回代码(即套接字已被通知已关闭),是确保客户端应用程序已收到数据的唯一方法。

但是,如果数据已成功传送(并确认)到对等方的计算机上,那么SO_LINGER就足够了。