Как правильно настроить сокет UDP с помощью UDP_CORK

Я создал эхо-сервер под UDP и работаю над клиентом, который разбивает данный файл на пакеты и передает его на сервер, который затем возвращает пакеты для повторной сборки клиентом.

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

#define LINE_SIZE 80

...
// s = socket descriptor.
...

int one = 1;
int zero = 0;

setsockopt(s, IPPROTO_UDP, UDP_CORK, &one, sizeof(one));  // cork

/* Send to server, receive from server, write to new file. */

FILE *orig, *copy;
char line[LINE_SIZE];

if ((orig = fopen(input + 3, "rb")) == NULL) // original file
    print_error(input);

if ((copy = fopen(filename, "wb")) == NULL)  // copy of file
    print_error("fopen");

while (fread(line, sizeof(char), LINE_SIZE, orig) > 0) {
    if (sendto(s, line, LINE_SIZE, 0, (struct sockaddr *)&srv, len) == -1)
    print_error("sendto");
}

setsockopt(s, IPPROTO_UDP, UDP_CORK, &zero, sizeof(zero));  // uncork

if (recvfrom(s, line, LINE_SIZE, 0, (struct sockaddr *)&srv, &len) == -1)
    print_error("recvfrom");

fwrite(line, sizeof(char), LINE_SIZE, copy);

Сервер указывает, что он получает только один пакет «нормального размера», а не заглушенный пакет, который мне хотелось бы. Из этого следует, что он отправляет обратно только один нормальный пакет, полученный клиентом через вызов recvfrom().

Я не уверен, что правильно настроил UDP_CORK. Верен ли второй аргумент? Я не знаком с тем, что на самом деле означает второй вариант, поскольку справочная страница не совсем ясна. Также возможно, что я неправильно понимаю, как работает пробка.

Несколько замечаний:

  • Я считаю себя программистом среднего уровня, но у меня мало опыта сетевого программирования.
  • Я понимаю, что UDP не лучший вариант для передачи файлов. Со временем это будет адаптировано к другому протоколу, который я помогаю разрабатывать.

Благодарю вас!


person Cody    schedule 24.05.2012    source источник


Ответы (1)


Насколько велик файл? Вы знаете, что дейтаграммы UDP ограничены размером 64 КБ, верно? И затем все, что превышает 1472 байта (1500 байтов доступной полезной нагрузки Ethernet минус минимум 20 байтов заголовка IP, меньше 8 байтов заголовка UDP), фрагментируется по IP.

Тогда вы никогда не проверяете возвращаемое значение setsockopt(2). Откуда вы знаете, что это удается?

Затем fread(3) сообщает вам, сколько он прочитал, но вы все еще пытаетесь отправить LINE_SIZE байт. Это не правильно.

person Nikolai Fetissov    schedule 24.05.2012
comment
Это совершенно верно. Я не принял во внимание размер, и файл, который я пробовал, не содержал большого количества описательных байтов до тех пор, пока не было превышено пороговое значение 1472. И спасибо, что указали на другие мои ошибки. Однако, если дейтаграмма фрагментирована по IP-адресу, не следует ли отправить остальные в одном или нескольких пакетах? Я получаю только первое. - person Cody; 25.05.2012
comment
Ядро может отказываться упаковывать в одну дейтаграмму больше, чем размер MTU, и хотя я не уверен в этом, тот факт, что вы получаете первый фрагмент, указывает на это направление. При фрагментации вы не получаете части дейтаграммы — вы либо получаете все целиком, либо ничего. - person Nikolai Fetissov; 25.05.2012