winsock 和 linux 套接字之间的区别
我正在开发一个类似 FTP 的程序,用于将大量小文件下载到 Xbox 360 devkit(使用 Winsock)上,并将其移植到 Playstation3(也是一个 devkit,并且使用 linux AFAIK)。 该程序使用 BSD 风格的套接字 (TCP)。 这两个程序都与同一服务器通信,下载相同的数据。 该程序循环遍历所有文件,如下所示:
for each file send(retrieve command) send(filename) receive(response) test response receive(size) receive(data)
在 Xbox 360 实现上,整个下载需要 1 分 27 秒,最后一次发送和第一次接收之间的时间大约需要 14 秒。 这对我来说似乎很合理。
对于相同的数据,Playstation3 实现需要 4 分 01 秒。 瓶颈似乎是在最后一次发送和第一次接收之间,占用了 3 分 43 秒的时间。 网络和磁盘时间都明显少于 Xbox 360。
这两个开发套件都与我的 PC 位于同一交换机上,该 PC 负责文件服务,并且该交换机上没有其他流量。
我尝试设置 TCP_NODELAY
标志,但这并没有显着改变事情。 我还尝试将 SO_SNDBUF
/SO_RCVBUF
设置为 625KB,这也没有显着影响时间。
我假设 Winsock 和 Linux 之间的 TCP/IP 堆栈实现存在差异; 是否可以设置一些套接字选项以使 linux 实现的行为更像 Winsock? 还有什么我没有考虑到的吗?
唯一的解决方案似乎是重写它,以便它一起发送所有文件请求,然后接收它们。
不幸的是,索尼的实现没有 TCP_CORK 选项,所以我不能说这是否是区别。
I'm developing an FTP-like program to download a large number of small files onto an Xbox 360 devkit (which uses Winsock), and porting it to Playstation3 (also a devkit, and uses linux AFAIK). The program uses BSD-style sockets (TCP). Both of the programs communicate with the same server, downloading the same data. The program iterates through all the files in a loop like this:
for each file send(retrieve command) send(filename) receive(response) test response receive(size) receive(data)
On the Xbox 360 implementation, the whole download takes 1:27, and the time between the last send and first receive takes about 14 seconds. This seems quite reasonable to me.
The Playstation3 implementation takes 4:01 for the same data. The bottleneck seems to be between the last send and first receive, which takes up 3:43 of that time. The network and disk times are both significantly less than the Xbox 360.
Both these devkits are on the same switch as my PC, which does the file serving, and there is no other traffic on said switch.
I've tried setting the TCP_NODELAY
flag, which didn't change things significantly. I've also tried setting the SO_SNDBUF
/SO_RCVBUF
to 625KB, which also didn't significantly affect the time.
I'm assuming that the difference lies between the TCP/IP stack implementations between Winsock and linux; is there some socket option that I could set to make the linux implementation behave more like Winsock? Is there something else I'm not accounting for?
The only solution looks to be to rewrite it so that it sends all the file requests together, then receives them all.
Unfortunately, Sony's implementation does not have the TCP_CORK option, so I cannot say if that is the difference.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要
TCP_CORK
。 它将阻止发送部分帧,从而增加吞吐量(以延迟为代价)——就像winsock一样。设置
v=0
在接收之前刷新帧:在大多数 Unix 上,您可以使用
writev()
或sendfile()
进一步提高吞吐量...You want
TCP_CORK
. It'll prevent partial frames from being sent increasing throughput (at the expense of latency) - just like winsock.Set
v=0
to flush the frames before receive:On most unixes you can improve your throughput further by using
writev()
orsendfile()
...Wireshark 是你的朋友,嗅探电线——查看数据包,看看每个数据包是如何排序的,看看你是否无法发现差异/问题。
在高延迟链路上,您确实需要确保尽可能多地缓冲,以保持每个 TCP 数据包达到最大状态。
发送合并通常是个好主意。 仅当发送端排队有多个未确认的帧时才会触发。 通常,如果您知道自己在做什么并且您的系统提供全面的缓冲,那么您应该仅禁用此功能,否则禁用它肯定会对高延迟网络上的系统性能产生负面影响。
对于最高吞吐量,缓冲区分界应该是路径 MTU 的精确因素。
Wireshark is your friend, sniff the wire -- look at the packets see how each is being sequenced and see if you can't spot the difference/problem.
On high latency links you really want to make sure you buffer as much as possible keeping each TCP packet maxed out.
Send coalesce is ususally a good idea. It only triggers when there is more than one unacknowledged frame queued on the send side. Typically you should ONLY disable this feature if you know what your doing and your system provides comprehensive buffering otherwise disabling it is certain to negativly effect system performance on high latency networks.
For highest throughput buffer demarc should be exact factors of path MTU.