C套接字:write()后跟close()会导致数据传输不完整
我试图编写一个基本的文件服务器,它从客户机获取文件名,并通过TCP将数据发送到客户机进行响应。我有一个工作客户机和服务器应用程序的大部分,但我观察一些奇怪的行为,考虑以下C套接字:write()后跟close()会导致数据传输不完整,c,sockets,tcp,network-programming,file-descriptor,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)) {
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\u fd
是通过网络发送的文件的文件描述符,conn\u fd
是connect()
edTCP
套接字的文件描述符
这似乎适用于小文件,但当我的文件变大(兆字节+)时,文件末尾的一些不一致的数据量将无法传输
我怀疑写后立即关闭()语句可能与此有关,因此在两个close()
语句之前,我尝试了1秒的sleep()
,我的客户机成功地接收到了所有数据
有没有比在服务器端执行sleep()
更好的方法来处理此问题?套接字上的成功“写入”并不意味着数据已成功发送到对等方
如果您使用的是unix衍生工具,则可以执行“man 7 socket”并检查“SO_LINGER”作为潜在的解决方案
编辑:由于EJP的评论(谢谢),我重新阅读了Stevens在“Unix网络编程”中关于确保向对等方交付所有数据的主题所说的内容。他说了以下内容(在第二版第1卷,第189页):
…我们看到,根据调用的函数(close或shutdown)以及是否设置了SO_LINGER套接字选项,当我们关闭连接端时,返回可能在三个不同的时间发生
shutdown()
,然后是等待零返回代码的read()
(即套接字已关闭的通知),这是确保客户端应用程序已收到数据的唯一方法
但是,如果数据已经成功地传递(并确认)到对等方的计算机上才是重要的,那么再多停留就足够了。您在这里演示过客户端代码或服务器代码吗?fsync(2)?我尝试过fsync()它没有解决问题。我认为您还有其他一些问题。TCP套接字不会像这样丢弃数据,除非网络关闭。您应该检查
read()
和close()的返回值(-1,尤其是它的errno
)
也是。不仅在这种情况下,而且在一般情况下。因此,LINGER并不能真正解决这个问题,它只是能够检测何时无法写入最终挂起的数据。在这种情况下,问题几乎肯定在接收端。