Подтвердить что ты не робот

Есть ли способ сбросить сокет POSIX?

Существует ли стандартный вызов для промывки стороны передачи сокета POSIX до конца на удаленном конце или это необходимо реализовать как часть протокола пользовательского уровня? Я огляделся вокруг обычных заголовков, но ничего не нашел.

4b9b3361

Ответ 1

Для сокетов Unix-домена вы можете использовать fflush(), но я думаю, что вы, вероятно, имеете в виду сетевые сокеты. На самом деле нет понятия о том, чтобы смывать их. Ближайшие вещи:

1) В конце сеанса вызовите shutdown(sock, SHUT_WR), чтобы закрыть записи в сокете.

2) В сокетах TCP, отключив алгоритм Nagle с sockopt TCP_NODELAY, который, как правило, является ужасной идеей, которая не будет надежно делать то, что вы хотите, даже если она, по-видимому, позаботится об этом при первоначальном расследовании.

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

Ответ 2

Как установить TCP_NODELAY и вернуть его обратно? Вероятно, это можно сделать непосредственно перед отправкой важных данных или по завершении отправки сообщения.

send(sock, "notimportant", ...);
send(sock, "notimportant", ...);
send(sock, "notimportant", ...);
int flag = 1; 
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
send(sock, "important data or end of the current message", ...);
flag = 0; 
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));

Как говорят страницы linux man

TCP_NODELAY... установка этого параметра заставляет явный поток ожидающего вывода...

Поэтому, вероятно, было бы лучше установить его после сообщения, но я не уверен, как он работает в других системах.

Ответ 3

В стандартном интерфейсе сокетов TCP/IP я не знаю, как очистить данные "до конца до конца" и убедиться, что они действительно были подтверждены.

Вообще говоря, если ваш протокол нуждается в передаче данных в реальном времени, как правило, лучше всего установить setsockopt() of TCP_NODELAY. Это отключает алгоритм Nagle в стеке протоколов, а write() или send() в сокете более непосредственно сопоставляет с отправителями в сеть.... вместо того, чтобы реализовать блокировку отправки, ожидая, что больше байт станет доступным, и используя все Таймеры уровня TCP, чтобы решить, когда отправлять. ПРИМЕЧАНИЕ. Отключение Nagle не отключает скользящее окно TCP или что-то еще, поэтому всегда безопасно делать.... но если вам не нужны свойства "в реальном времени", пакетные накладные расходы могут немного возрасти.

Кроме того, если обычные механизмы сокетов TCP не подходят вашему приложению, тогда обычно вам нужно вернуться к использованию UDP и создать свои собственные функции протокола в основных свойствах send/receive UDP. Это очень часто встречается, когда ваш протокол имеет особые потребности, но не стоит недооценивать сложность этого, и все это стабильно и функционально корректно во всех, но относительно простых приложениях. В качестве отправной точки тщательное изучение функций проектирования TCP прольет свет на многие из проблем, которые необходимо учитывать.

Ответ 4

В RFC 1122 название вещи, которую вы ищете, это "PUSH". Хотя я не знаю TCP API, который реализует "PUSH".

Некоторые ответы и комментарии касаются алгоритма Нагла. Большинство из них, по-видимому, считают, что алгоритм Нэгла задерживает каждую отправку. Это предположение неверно. Nagle задерживает отправку только тогда, когда предыдущий пакет еще не подтвержден (http://www.unixguide.net/network/socketfaq/2.11.shtml).

Чтобы немного упростить это: TCP пытается сразу же отправить первый пакет (строки пакетов), но задерживает последующие пакеты до тех пор, пока не будет достигнут тайм-аут или не будет принят первый пакет - в зависимости от того, что произойдет раньше.

Одним из решений является избежание этих "последующих пакетов". Если ваше приложение вызывает send() более одного раза для передачи одного составного запроса, попробуйте переписать приложение. Соберите запрос в пользовательском пространстве, затем вызовите send(). Один раз.

Кроме того, когда буфер отправки содержит достаточно данных для заполнения максимального размера сетевого пакета, Nagle также не задерживает. Это означает, что Нагл не (действительно) задерживает отправку большого объема, даже если вы send() объемные данные в небольших кусках.

Ответ 5

Я думаю, что было бы чрезвычайно сложно, если не невозможно реализовать правильно. В чем смысл "флеша" в этом контексте? Байты передаются в сеть? Байты, подтвержденные стеком приемника TCP? Байты перешли в приложение пользовательского режима получателя? Байт полностью обработан приложением пользовательского режима?

Похоже, вам нужно сделать это на уровне приложения...

Ответ 6

TCP дает только наилучшую поставку, поэтому действие, связанное с тем, что все байты оставляют машину A, асинхронно, и все они были получены на машине B. Степень протокола TCP/IP знает, конечно, но я не знать какой-либо способ опроса стека TCP, чтобы узнать, было ли подтверждено все отправленные сообщения.

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

Ответ 7

Вы можете установить параметр tcp SO_LINGER для установки определенного тайм-аута, а затем закрыть сокет, чтобы убедиться, что все данные были отправлены (или обнаруживают отказ от этого) при закрытии соединения. Кроме того, TCP является протоколом "наилучшего усилия", и он не дает никаких реальных гарантий того, что данные когда-либо будут на самом деле достигнут пункта назначения (в отличие от того, что, по-видимому, кажется, кажется), он просто пытается получить его в правильном порядке и как можно скорее.

Ответ 8

Использовать fsync():

sock_fd - это дескриптор целочисленного файла из вызова socket (...,...)

FSYNC (sock_fd);