【问题标题】:Socket Programming Best Practices?套接字编程最佳实践?
【发布时间】:2012-02-01 12:10:04
【问题描述】:

我正在设计一个文件同步应用程序(如 DropBox)。客户端在端口 443 上与服务器保持持久的安全 (SSL) TCP 套接字。每当在客户端上创建/更改/删除文件时,都会通过套接字将包含相关数据的数据包发送到服务器,服务器将其处理为更新服务器上的文件。同样,当服务器发生变化时,它会将相关数据发送给客户端,然后客户端更新本地副本。

当服务器位于本地计算机或本地 LAN 上时,这绝对可以正常工作。我担心的是客户端在不可靠的网络上时。 所以我的问题是在设计这样的应用程序时要考虑哪些最佳做法和问题?

例如,当在客户端创建文件时,客户端应该只是将数据发送到服务器并忘记它,还是应该在特定时间段内等待服务器的确认,发送失败又是数据?以及什么样的认可?

【问题讨论】:

    标签: sockets tcp


    【解决方案1】:

    TCP 抽象了许多网络问题:数据包总是按顺序到达,如果服务器不确认已收到数据包,则重新发送。不可靠的网络会导致流量变慢,因为必须重新发送数据包。

    如果连接丢失,你的 read() 和 write() 调用将返回错误返回值,所以你必须处理它。

    【讨论】:

    • 哦,那很好。所以我不需要担心丢包。但我想我仍然需要在应用层中发送确认,作为对下面答案的评论中提到的“否”。
    • 所以我的应用程序是否应该继续将数据推送到套接字,而不用担心任何事情。例如,假设客户端要向服务器发送一个 10 GB 的文件,而连接速度确实很慢。应用程序是否应该继续将数据写入输出缓冲区?如果网络慢,缓冲区不会溢出吗?
    • 如果你使用sendfile(2) 之类的东西,它会返回它设法写入的字节数。然后,您可以轮询 FD 以了解写入准备情况并尝试写入更多内容。
    • @Tarandeep 如果您使用 TCP,它应该会自动管理速度。
    • @Tarandeep Gill TCP 有流量控制,所以缓冲区不会溢出。您的 read()/write() 调用将阻塞(除非您小心,否则可能永远阻塞),直到可以发送数据,或者如果您的套接字是非阻塞的,write() 将失败并告诉您缓冲区已满那一刻。
    【解决方案2】:

    客户端与服务器保持一个持久的安全 (SSL) TCP 套接字

    [..]

    客户端应该直接将数据发送到服务器并忘记它,还是应该在一定时间内等待服务器的确认,失败再次发送数据?

    如果您使用的是 UDP,则必须这样做。但既然你使用的是 TCP,那一切都已经为你完成了。

    http://en.wikipedia.org/wiki/Transmission_Control_Protocol

    您应该知道 TCP 是一种面向流的协议,因此您的数据到达的方式可能与您发送它的方式不同(即它可能一次到达一个字节,或者一次全部到达)。

    【讨论】:

    • 并非如此。您不知道另一端的应用程序层是否一切正常,只是因为 TCP 没有出错。例如服务器端可能会耗尽磁盘空间,它可能会在客户端发送最后一个字节但在此之前到达服务器应用程序之前崩溃,以及您可能需要关心的许多其他应用程序特定的东西。
    • 这超出了“套接字编程”的范围,不是吗?
    • 感谢 cmets 伙计们,对我对 Sjoerd 上述回答的评论有何回应?
    【解决方案3】:

    即使服务器是本地主机,您也应该使用确认。想象一下在发送信息时发生了某种连接问题。您需要某种方式来了解操作的结果(例如,使用确认系统)。

    我会使用比简单的 ACK/NACK 回复更复杂的方法。例如,如果您更改了客户端中的某些文件,则在从客户端向服务器发送信息后,服务器应回复受更新操作影响的文件的数量(或带有名称的列表)。这样,客户端可以验证一切正常,或采取相应的行动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 2015-08-11
      • 1970-01-01
      • 2011-06-29
      • 2011-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多