我正在开发一个类似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。
这两个devkits都与我的PC处于同一个交换机上,后者执行文件服务,并且所述交换机上没有其他流量。
我尝试设置TCP_NODELAY
标志,这并没有显着改变。我也尝试将SO_SNDBUF
/ SO_RCVBUF
设置为625KB,这也没有显着影响时间。
我假设Winsock和linux之间的TCP / IP堆栈实现之间存在差异;是否有一些套接字选项,我可以设置使Linux实现更像Winsock?还有其他我不记得的东西吗?
唯一的解决方案是重写它,以便它将所有文件请求一起发送,然后全部接收它们。
不幸的是,Sony的实现没有TCP_CORK选项,所以我不能说这是不同的。
答案 0 :(得分:2)
你想要TCP_CORK
。它会阻止部分帧被发送,从而增加吞吐量(以延迟为代价) - 就像winsock一样。
int v,vlen;
v=1; vlen=sizeof(v);
setsockopt(fd, IPPROTO_TCP, TCP_CORK, &v, &vlen);
设置v=0
以在接收之前刷新帧:
int v,vlen;
v=0; vlen=sizeof(v);
setsockopt(fd, IPPROTO_TCP, TCP_CORK, &v, &vlen);
在大多数unix上,您可以使用writev()
或sendfile()
...
答案 1 :(得分:1)
Wireshark是你的朋友,嗅探电线 - 查看数据包,看看每个数据包是如何排序的,看看你是否无法发现差异/问题。
在高延迟链接上,您确实希望尽可能地缓冲每个TCP数据包的最大值。
发送合并通常是一个好主意。它仅在发送方排队的多个未确认帧时触发。通常情况下,如果您知道自己在做什么,并且系统提供全面的缓冲,那么仅禁用此功能,否则禁用它肯定会对高延迟网络上的系统性能产生负面影响。
对于最高吞吐量,缓冲区划分应该是路径MTU的精确因子。