Разница между розетками winsock и linux - PullRequest
6 голосов
/ 26 ноября 2008

Я разрабатываю FTP-подобную программу для загрузки большого количества маленьких файлов в devbox для Xbox 360 (которая использует 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.

Оба этих устройства находятся на том же коммутаторе, что и мой компьютер, который выполняет обслуживание файлов, и на указанном коммутаторе нет другого трафика.

Я попытался установить флаг TCP_NODELAY, который ничего не изменил. Я также попытался установить SO_SNDBUF / SO_RCVBUF на 625 КБ, что также не оказало существенного влияния на время.

Я предполагаю, что разница лежит между реализациями стека TCP / IP между Winsock и linux; Есть ли какой-либо параметр сокета, который я мог бы установить, чтобы реализация Linux более походила на Winsock? Есть ли что-то еще, что я не учитываю?

Единственное решение состоит в том, чтобы переписать его так, чтобы он отправлял все запросы файлов вместе, а затем получал их все.

К сожалению, в реализации Sony нет опции TCP_CORK, поэтому я не могу сказать, в этом ли разница.

Ответы [ 2 ]

2 голосов
/ 26 ноября 2008

Вы хотите 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 голос
/ 26 ноября 2008

Wireshark - ваш друг, отнюдь провод - посмотрите на пакеты, посмотрите, как каждый из них упорядочен, и посмотрите, не можете ли вы определить разницу / проблему.

На каналах с высокой задержкой вы действительно хотите обеспечить максимальную буферизацию, сохраняя максимальный размер каждого TCP-пакета.

Отправка слияния обычно является хорошей идеей. Он срабатывает только в том случае, если на стороне отправки находится в очереди более одного неподтвержденного кадра. Как правило, вам следует ТОЛЬКО отключить эту функцию, если вы знаете, что делаете, и ваша система обеспечивает всеобъемлющую буферизацию, в противном случае ее отключение наверняка негативно повлияет на производительность системы в сетях с высокой задержкой.

Для максимальной пропускной способности буфера демаркация должна быть точным фактором пути MTU.

...