Socket编程最佳实践?

5
我正在设计一个文件同步应用程序(类似于DropBox)。客户端在443端口与服务器保持持久的安全(SSL)TCP套接字连接。每当客户端创建/更改/删除文件时,会将包含相关数据的数据包通过套接字发送到服务器,服务器会处理它以更新服务器上的文件。同样,当服务器上有变化时,它会将相关数据发送到客户端,然后客户端会更新本地副本。
当服务器位于本地计算机或本地局域网上时,这完全正常工作。但是,我担心的是当客户端处于不可靠的网络上时。因此,我的问题是,在设计这样的应用程序时,需要考虑哪些最佳实践和问题?
例如,假设在客户端上创建文件时,客户端应该只将数据发送到服务器并忘记它,还是应该在一定时间内等待服务器的确认,否则重新发送数据?什么样的确认方式?
3个回答

7
TCP抽象了许多网络问题:数据包总是按顺序到达,如果服务器没有确认已接收数据包,则会重新发送。不可靠的网络会导致流量变慢,因为需要重新发送数据包。
如果连接丢失,您的read()和write()调用将返回错误值,因此您必须处理这个问题。

哦,那很好。所以我不需要担心丢失的数据包。但是我想我仍然需要在应用层发送确认,就像“nos”在下面的答案评论中提到的那样。 - Tarandeep Gill
那么我的应用程序是否应该只是不必担心任何事情而持续向套接字推送数据呢?例如,假设客户端必须向服务器发送一个大小为10 GB的文件,并且连接速度非常慢。应用程序是否应该只是持续将数据写入输出缓冲区?如果网络速度很慢,缓冲区会不会溢出? - Tarandeep Gill
如果您使用类似 sendfile(2) 的东西,它将返回它成功写入的字节数。然后,您可以轮询 FD 以检查其是否准备好进行写操作,并尝试继续写入更多数据。 - James M
@Tarandeep 如果你正在使用TCP,它应该会自动管理速度。 - Maiku Mori
客户端是用C++编写的。因此,我假设当我使用类似socket->write(fileData)的东西将数据写入套接字时,它不会返回,直到所有数据都已通过网络发送到服务器。这正确吗? - Tarandeep Gill
1
@Tarandeep Gill TCP有流量控制,因此缓冲区不会溢出。你的read()/write()调用将被阻塞(可能永远,除非你小心),直到数据可以发送,或者如果你的套接字是非阻塞的,write()将失败并告诉你缓冲区目前已满。 - nos

1
客户端与服务器保持一个持久的安全(SSL)TCP套接字连接。对于这种情况,客户端应该只是将数据发送到服务器并忘记它,还是应该在一定时间内等待服务器的确认,如果没有收到确认,则重新发送数据?
如果您使用UDP,那么必须这样做。但是,由于您正在使用TCP,所有这些都已经为您完成了。

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

你应该意识到TCP是一种面向流的协议,因此你发送的数据可能不会以相同的方式到达(即它可能一次只到达一个字节,或者一次性全部到达)。

2
并不完全如此。仅仅因为TCP没有出错,并不能保证在另一端的应用层一切都正常。例如,服务器端可能会出现磁盘空间不足的情况,在客户端发送最后一个字节但尚未到达服务器应用程序之前就崩溃,以及其他许多需要关注的应用程序特定问题。 - nos
这超出了“套接字编程”的范畴,不是吗? - James M
谢谢大家的评论,对于我在Sjoerd上面的回复有什么反应吗? - Tarandeep Gill

1

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

我会使用比简单的 ACK/NACK 回复更复杂的东西。例如,如果您更改了客户端中的一些文件,在将信息从客户端发送到服务器后,服务器应该回复受更新操作影响的文件数(或名称列表)。这样,客户端就可以验证一切正常或采取相应措施。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接