Как закрыть сокет в windows

Обновлено: 05.07.2024

Именованные каналы пригодны для организации межпроцессного взаимодействия как в случае процессов, выполняющихся на одной и той же системе, так и в случае процессов, выполняющихся на компьютерах, связанных друг с другом локальной или глобальной сетью. Эти возможности были продемонстрированы на примере клиент-серверной системы, разработанной в главе 11, начиная с программы 11.2.

Однако как именованные каналы, так и почтовые ящики (в отношении которых для простоты мы будем использовать далее общий термин — "именованные каналы", если различия между ними не будут играть существенной роли) обладают тем недостатком, что они не являются промышленным стандартом. Это обстоятельство усложняет перенос программ наподобие тех, которые рассматривались в главе 11, в системы, не принадлежащие семейству Windows, хотя именованные каналы не зависят от протоколов и могут выполняться поверх многих стандартных промышленных протоколов, например TCP/IP.

Возможность взаимодействия с другими системами обеспечивается в Windows поддержкой сокетов (sockets) Windows Sockets — совместимого и почти точного аналога сокетов Berkeley Sockets, де-факто играющих роль промышленного стандарта. В этой главе использование API Windows Sockets (или "Winsock") показано на примере модифицированной клиент-серверной системы из главы 11. Результирующая система способна функционировать в глобальных сетях, использующих протокол TCP/IP, что, например, позволяет серверу принимать запросы от клиентов UNIX или каких-либо других, отличных от Windows систем.

В данной главе указанная клиент-серверная система используется в качестве механизма демонстрации интерфейса Winsock, и в процессе того, как сервер будет модифицироваться, в него будут добавляться новые интересные возможности. В частности, нами будут впервые использованы точки входа DLL (глава 5) и внутрипроцессные серверы DLL. (Эти новые средства можно было включить уже в первоначальную версию программы в главе 11, однако это отвлекло бы ваше внимание от разработки основной архитектуры системы.) Наконец, дополнительные примеры покажут вам, как создаются безопасные реентерабельные многопоточные библиотеки.

Поскольку интерфейс Winsock должен соответствовать промышленным стандартам, принятые в нем соглашения о правилах присвоения имен и стилях программирования несколько отличаются от тех, с которыми мы сталкивались в процессе работы с описанными ранее функциями Windows. Строго говоря, Winsock API не является частью Win32/64. Кроме того, Winsock предоставляет дополнительные функции, не подчиняющиеся стандартам; эти функции используются лишь в случае крайней необходимости. Среди других преимуществ, обеспечиваемых Winsock, следует отметить улучшенную переносимость результирующих программ на другие системы.

Winsock API разрабатывался как расширение Berkley Sockets API для среды Windows и поэтому поддерживается всеми системами Windows. К преимуществам Winsock можно отнести следующее:

• Перенос уже имеющегося кода, написанного для Berkeley Sockets API, осуществляется непосредственно.

• Системы Windows легко встраиваются в сети, использующие как версию IPv4 протокола TCP/IP, так и постепенно распространяющуюся версию IPv6. Помимо всего остального, версия IPv6 допускает использование более длинных IP-адресов, преодолевая существующий 4-байтовый адресный барьер версии IPv4.

• Сокеты могут использоваться совместно с перекрывающимся вводом/выводом Windows (глава 14), что, помимо всего прочего, обеспечивает возможность масштабирования серверов при увеличении количества активных клиентов.

• Сокеты можно рассматривать как дескрипторы (типа HANDLE) файлов при использовании функций ReadFile и WriteFile и, с некоторыми ограничениями, при использовании других функций, точно так же, как в качестве дескрипторов файлов сокеты применяются в UNIX. Эта возможность оказывается удобной в тех случаях, когда требуется использование асинхронного ввода/вывода и портов завершения ввода/вывода.

• Существуют также дополнительные, непереносимые расширения.

Winsock API поддерживается библиотекой DLL (WS2_32.DLL), для получения доступа к которой следует подключить к программе библиотеку WS_232.LIB. Эту DLL следует инициализировать с помощью нестандартной, специфической для Winsock функции WSAStartup, которая должна быть первой из функций Winsock, вызываемых программой. Когда необходимость в использовании функциональных возможностей Winsock отпадает, следует вызывать функцию WSACleanup. Примечание. Префикс WSA означает "Windows Sockets asynchronous …" ("Асинхронный Windows Sockets …"). Средства асинхронного режима Winsock нами здесь не используются, поскольку при возникновении необходимости в выполнении асинхронных операций мы можем и будем использовать потоки.

int WSAStartup(WORD wVersionRequired, LPWSADATA ipWSAData);

Параметры

wVersionRequired — указывает старший номер версии библиотеки DLL, который вам требуется и который вы можете использовать. Как правило, версии 1.1 вполне достаточно для того, чтобы обеспечить любое взаимодействие с другими системами, в котором у вас может возникнуть необходимость. Тем не менее, во всех системах Windows, включая Windows 9x, доступна версия Winsock 2.0, которая и используется в приведенных ниже примерах. Версия 1.1 считается устаревшей и постепенно выходит из употребления.

Функция возвращает ненулевое значение, если запрошенная вами версия данной DLL не поддерживается.

Младший байт параметра wVersionRequired указывает основной номер версии, а старший байт — дополнительный. Обычно используют макрос MAKEWORD; таким образом, выражение MAKEWORD (2,0) представляет версию 2.0.

ipWSAData — указатель на структуру WSADATA, которая возвращает информацию о конфигурации DLL, включая старший доступный номер версии. О том, как интерпретировать ее содержимое, вы можете прочитать в материалах оперативной справки Visual Studio.

Чтобы получить более подробную информацию об ошибках, можно воспользоваться функцией WSAGetLastError, но для этой цели подходит также функция GetLastError, а также функция ReportError, разработанная в главе 2.

По окончании работы программы, а также в тех случаях, когда необходимости в использовании сокетов больше нет, следует вызывать функцию WSACleanup, чтобы библиотека WS_32.DLL, обслуживающая сокеты, могла освободить ресурсы, распределенные для этого процесса.

Инициализировав Winsock DLL, вы можете использовать стандартные (Berkeley Sockets) функции для создания сокетов и соединений, обеспечивающих взаимодействие серверов с клиентами или взаимодействие равноправных узлов сети между собой.

Используемый в Winsock тип данных SOCKET аналогичен типу данных HANDLE в Windows, и его даже можно применять совместно с функцией ReadFile и другими функциями Windows, требующими использования дескрипторов типа HANDLE. Для создания (или открытия) сокета служит функция socket.

SOCKET socket(int af, int type, int protocol);

Параметры

Тип данных SOCKET фактически определяется как тип данных int, потому код UNIX остается переносимым, не требуя привлечения типов данных Windows.

af — обозначает семейство адресов, или протокол; для указания протокола IP (компонент протокола TCP/IP, отвечающий за протокол Internet) следует использовать значение PF_INET (или AF_INET, которое имеет то же самое числовое значение, но обычно используется при вызове функции bind).

type — указывает тип взаимодействия: ориентированное на установку соединения (connection-oriented communication), или потоковое (SOCK_STREAM), и дейтаграммное (datagram communication) (SOCK_DGRAM), что в определенной степени сопоставимо соответственно с именованными каналами и почтовыми ящиками.

protocol — является излишним, если параметр af установлен равным AF_INET; используйте значение 0.

В случае неудачного завершения функция socket возвращает значение INVALID_SOCKET.

Winsock можно использовать совместно с протоколами, отличными от TCP/IP, указывая различные значения параметра protocol; мы же будем использовать только протокол TCP/IP.

Как и в случае всех остальных стандартных функций, имя функции socket не должно содержать прописных букв. Это является отходом от соглашений, принятых в Windows, и продиктовано необходимостью соблюдения промышленных стандартов.

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

Если не оговорено иное, типом сокетов в наших примерах всегда будет SOCK_STREAM. Сокеты типа SOCK_DGRAM рассматривается далее в этой главе.

Следующий шаг заключается в привязке сокета к его адресу и конечной точке (endpoint) (направление канала связи от приложения к службе). Вызов socket, за которым следует вызов bind, аналогичен созданию именованного канала. Однако не существует имен, используя которые можно было бы различать сокеты данного компьютера. Вместо этого в качестве конечной точки службы используется номер порта (port number). Любой заданный сервер может иметь несколько конечных точек. Прототип функции bind приводится ниже.

int bind(SOCKET s, const struct sockaddr *saddr, int namelen);

Параметры

s — несвязанный сокет, возвращенный функцией socket.

saddr — заполняется перед вызовом и задает протокол и специфическую для протокола информацию, как описано ниже. Кроме всего прочего, в этой структуре содержится номер порта.

namelen — присвойте значение sizeof (sockaddr).

В случае успешного выполнения функция возвращает значение 0, иначе SOCKET_ERROR. Структура sockaddr определяется следующим образом:

Первый член этой структуры, sa_family, обозначает протокол. Второй член, sa_data, зависит от протокола. Internet-версией структуры sa_data является структура sockaddr_in:

typedef struct sockaddr_in SOCKADDR_IN, *PSOCKADDR IN;

Обратите внимание на использование типа данных short integer для номера порта. Кроме того, номер порта и иная информация должны храниться с соблюдением подходящего порядка следования байтов, при котором старший байт помещается в крайней позиции справа (big-endian), чтобы обеспечивалась двоичная совместимость с другими системами. В структуре sin_addr содержится подструктура s_addr, заполняемая уже знакомым нам 4-байтовым IP-адресом, например 127.0.0.1, указывающим систему, чей запрос на образование соединения должен быть принят. Обычно удовлетворяются запросы любых систем, в связи с чем следует использовать значение INADDR_ANY, хотя этот символический параметр должен быть преобразован к корректному формату, как показано в приведенном ниже фрагменте кода.

Для преобразования текстовой строки с IP-адресом к требуемому формату можно использовать функцию inet_addr, поэтому член sin_addr.s_addr переменной sockaddr_in инициализируется следующим образом:

О связанном сокете, для которого определены протокол, номер порта и IP-адрес, иногда говорят как об именованном сокете (named socket).

Функция listen делает сервер доступным для образования соединения с клиентом. Аналогичной функции для именованных каналов не существует.

int listen(SOCKET s, int nQueueSize);

Параметр nQueueSize указывает число запросов на соединение, которые вы намерены помещать в очередь сокета. В версии Winsock 2.0 значение этого параметра не имеет ограничения сверху, но в версии 1.1 оно ограничено предельным значением SOMAXCON (равным 5).

Наконец, сервер может ожидать соединения с клиентом, используя функцию accept, возвращающую новый подключенный сокет, который будет использоваться в операциях ввода/вывода. Заметьте, что исходный сокет, который теперь находится в состоянии прослушивания (listening state), используется исключительно в качестве параметра функции accept, а не для непосредственного участия в операциях ввода/вывода.

Функция accept блокируется до тех пор, пока от клиента не поступит запрос соединения, после чего она возвращает новый сокет ввода/вывода. Хотя рассмотрение этого и выходит за рамки данной книги, возможно создание неблокирующихся сокетов, а в сервере (программа 12.2) для приема запроса используется отдельный поток, что позволяет создавать также неблокирующиеся серверы.

SOCKET accept(SOCKET s, LPSOCKADDR lpAddr, LPINT lpAddrLen);

Параметры

s — прослушивающий сокет. Чтобы перевести сокет в состояние прослушивания, необходимо предварительно вызвать функции socket, bind и listen.

lpAddr — указатель на структуру sockaddr_in, предоставляющую адрес клиентской системы.

lpAddrLen — указатель на переменную, которая будет содержать размер возвращенной структуры sockaddr_in. Перед вызовом функции accept эта переменная должна быть инициализирована значением sizeof(struct sockaddr_in).

Когда работа с сокетом закончена, его следует закрыть, вызвав функцию closesocket(SOCKET s). Сначала сервер закрывает сокет, созданный функцией accept, а не прослушивающий сокет, созданный с помощью функции socket. Сервер должен закрывать прослушивающий сокет только тогда, когда завершает работу или прекращает принимать клиентские запросы соединения. Даже если вы работаете с сокетом как с дескриптором типа HANDLE и используете функции ReadFile и WriteFile, уничтожить сокет одним только вызовом функции CloseHandle вам не удастся; для этого следует использовать функцию closesocket.

Ниже приводится фрагмент кода, показывающий, как создать сокет и организовать прием клиентских запросов соединения.

В этом примере используются две стандартные функции: htons ("host to network short" — "ближняя связь") и htonl ("host to network long" — "дальняя связь"), которые преобразуют целые числа к форме с обратным порядком байтов, требуемой протоколом IP.

Номером порта сервера может быть любое число из диапазона, допустимого для целых чисел типа short integer, но для определенных пользователем служб обычно используются числа в диапазоне 1025—5000. Порты с меньшими номерами зарезервированы для таких известных служб, как telnet или ftp, в то время как порты с большими номерами предполагаются для использования других стандартных служб.

Когда работа с сокетом закончена, его следует закрыть, вызвав функцию closesocket(SOCKET s). Сначала сервер закрывает сокет, созданный функцией accept, а не прослушивающий сокет, созданный с помощью функции socket. Сервер должен закрывать прослушивающий сокет только тогда, когда завершает работу или прекращает принимать клиентские запросы соединения. Даже если вы работаете с сокетом как с дескриптором типа HANDLE и используете функции ReadFile и WriteFile, уничтожить сокет одним только вызовом функции CloseHandle вам не удастся; для этого следует использовать функцию closesocket.

17.7. Ошибки сокетов

17.7. Ошибки сокетов Некоторые значения errno встречаются только при работе с сокетами. Ниже приведен список специфических ошибок сокетов вместе с краткими их описаниями. EADDRINUSE Запрашиваемый адрес уже используется и не может быть переприсвоен. EADDRNOTAVAIL Запрашивается

Программный интерфейс сокетов

Программный интерфейс сокетов Вы уже познакомились с интерфейсом сокетов при обсуждении реализации межпроцессного взаимодействия в BSD UNIX. Поскольку сетевая поддержка впервые была разработана именно для BSD UNIX, интерфейс сокетов и сегодня является весьма

Пара сокетов

Пара сокетов Пара сокетов (socket pair) для соединения TCP — это кортеж (группа взаимосвязанных элементов данных или записей) из четырех элементов, определяющий две конечных точки соединения: локальный IP-адрес, локальный порт TCP, удаленный IP-адрес и удаленный порт TCP. В SCRIPT

3.2. Структуры адреса сокетов

3.2. Структуры адреса сокетов Большинство функций сокетов используют в качестве аргумента указатель на структуру адреса сокета. Каждый набор протоколов определяет свою собственную структуру адреса сокетов. Имена этих структур начинаются с sockaddr_ и заканчиваются

7.4. Состояния сокетов

7.4. Состояния сокетов Для некоторых параметров сокетов время их установки или получения зависит некоторым образом от состояния сокета. Далее мы обсудим эту зависимость для тех параметров, к которым это относится.Следующие параметры сокетов наследуются присоединенным

7.5. Общие параметры сокетов

7.5. Общие параметры сокетов Мы начнем с обсуждения общих параметров сокетов. Эти параметры не зависят от протокола (то есть они управляются не зависящим от протокола кодом внутри ядра, а не отдельным модулем протокола, такого как IPv4), но некоторые из них применяются только

7.6. Параметры сокетов IPv4

7.8. Параметры сокетов IPv6

7.8. Параметры сокетов IPv6 Эти параметры сокетов обрабатываются IPv6 и имеют аргумент level, равный IPPROTO_IPV6. Мы отложим обсуждение пяти параметров сокетов многоадресной передачи до раздела 21.6. Отметим, что многие из этих параметров используют вспомогательные данные с функцией

7.9. Параметры сокетов TCP

7.9. Параметры сокетов TCP Для сокетов TCP предусмотрены два специальных параметра. Для них необходимо указывать level

7.10. Параметры сокетов SCTP

7.10. Параметры сокетов SCTP Относительно большое количество параметров, определенных для сокетов SCTP (17 на момент написания этой книги), дают возможность разработчику приложения более точно контролировать его поведение. Параметр level для сокетов SCTP должен принимать значение

15.4. Функции сокетов

15.4. Функции сокетов Функции сокетов применяются к доменным сокетам Unix с учетом некоторых особенностей и ограничений. Далее мы перечисляем требования POSIX, указывая, где они применимы. Отметим, что на сегодняшний день не все реализации соответствуют этим

28.2. Создание символьных сокетов

28.2. Создание символьных сокетов При создании символьных сокетов выполняются следующие шаги:1. Символьный сокет создается функцией socket со вторым аргументом SOCK_RAW. Третий аргумент (протокол) обычно ненулевой. Например, для создания символьного сокета IPv4 следует написать:int

27.3. Программирование сокетов

27.3. Программирование сокетов 27.3.1. Что такое сокет? Сокет — это двунаправленный канал между двумя компьютерами в сети, который обеспечивает конечную точку соединения. «Двунаправленный» означает, что данный могут передаваться в двух направлениях — от клиента к серверу и

5.5.1. Концепции сокетов

5.5.1. Концепции сокетов При создании сокета необходимо задать три параметра, тип взаимодействия, пространство имен и протокол.Тип взаимодействия определяет способ интерпретации передаваемых данных и число абонентов. Данные, посылаемые через сокет, формируются в блоки,

5.5.7. Пары сокетов

5.5.7. Пары сокетов Как было показано выше, функция pipe() создает два дескриптора для входного и выходного концов канала. Возможности каналов ограничены, так как с файловыми дескрипторами должны работать связанные процессы и данные через канал передаются только в одном

кто-нибудь знает, как закрыть сокет TCP или UDP для одного соединения через командную строку windows?

Googling об этом, я видел, что некоторые люди спрашивают то же самое. Но ответы выглядели как ручная страница команд netstat или netsh, сосредоточенных на том, как контролировать порты. Мне не нужны ответы о том, как их контролировать (я уже это делаю). Я хочу закрыть/убить их.

EDIT, для уточнения: предположим, что мой сервер прослушивает TCP-порт 80. Клиент для него выделяется соединение и порт 56789. Затем я обнаруживаю, что это соединение нежелательно (например, этот пользователь делает плохие вещи, мы попросили их остановиться, но соединение не было сброшено где-то по пути). Обычно я добавлял брандмауэр, чтобы выполнить работу, но это заняло бы некоторое время, и я был в чрезвычайной ситуации. Убийство процесса, которому принадлежит соединение, действительно плохая идея здесь, потому что это снимет сервер (все пользователи потеряют функциональность, когда мы просто хотите выборочно и временно отбросить это одно соединение).

Да, это возможно. Вам не обязательно быть текущим процессом, владеющим сокетом, чтобы закрыть его. На мгновение подумайте, что удаленная машина, сетевая карта, сетевой кабель и ваша ОС могут привести к закрытию сокета.

учтите также, что программное обеспечение Fiddler и Desktop VPN может вставляться в сетевой стек и показывать Вам весь ваш трафик или перенаправлять весь ваш трафик.

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

существует по крайней мере одна программа (currports также), который делает именно это, и я использовал его сегодня с целью закрытия определенных сокетов в процессе, который был запущен до запуска CurrPorts. Для этого вы должны запустить его как администратор, конечно.

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

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

Закрывает подключение Socket и освобождает все связанные ресурсы.

Перегрузки

Закрывает подключение Socket и освобождает все связанные ресурсы.

Закрывает подключение Socket и освобождает все связанные ресурсы с заданным временем ожидания, чтобы разрешить отправку данных в очереди.

Close()

Закрывает подключение Socket и освобождает все связанные ресурсы.

Примеры

В следующем примере кода закрывается Socket .

Комментарии

CloseМетод закрывает подключение к удаленному узлу и освобождает все управляемые и неуправляемые ресурсы, связанные с Socket . После закрытия Connected свойству присваивается значение false .

Для протоколов, ориентированных на соединение, рекомендуется вызывать Shutdown метод перед вызовом Close метода. Это гарантирует, что все данные отправляются и получаются на подключенном сокете до его закрытия.

Если необходимо вызвать Close без первого вызова Shutdown , можно убедиться, что данные, поставленные в очередь для исходящей передачи, будут отправлены, задав DontLinger Socket для параметра значение false и указав интервал времени ожидания, отличный от нуля. Close будет блокироваться до тех пор, пока эти данные не будут отправлены или пока не истечет указанное время ожидания. Если задано DontLinger значение false и задан нулевой интервал времени ожидания, Close освобождает соединение и автоматически удаляет исходящие данные из очереди.

Чтобы присвоить DontLinger параметру сокета значение false , создайте LingerOption , задайте для свойства Enabled значение true , а для LingerTime Свойства — требуемый период времени ожидания. Используйте его LingerOption вместе с DontLinger параметром Socket для вызова SetSocketOption метода.

См. также раздел

Применяется к

Close(Int32)

Закрывает подключение Socket и освобождает все связанные ресурсы с заданным временем ожидания, чтобы разрешить отправку данных в очереди.

Параметры

Примеры

В следующем примере кода показано, как закрыть Socket .

Комментарии

CloseМетод закрывает подключение к удаленному узлу и освобождает все управляемые и неуправляемые ресурсы, связанные с Socket . После закрытия Connected свойству присваивается значение false .

Для протоколов, ориентированных на соединение, рекомендуется вызывать метод Shutdown перед вызовом метода Close . Это гарантирует, что все данные отправляются и получаются на подключенном сокете до его закрытия.

Если необходимо вызвать Close без первого вызова Shutdown , можно убедиться, что данные, поставленные в очередь для исходящей передачи, будут отправлены, задав DontLinger для параметра значение false и указав интервал времени ожидания, отличный от нуля. Close будет блокироваться до тех пор, пока эти данные не будут отправлены или пока не истечет указанное время ожидания. Если задано DontLinger значение false и задан нулевой интервал времени ожидания, Close освобождает соединение и автоматически удаляет исходящие данные из очереди.

Чтобы присвоить DontLinger параметру сокета значение false , создайте LingerOption , задайте для свойства Enabled значение true и задайте LingerTime для свойства требуемый период ожидания. Используйте его LingerOption вместе с DontLinger параметром Socket для вызова SetSocketOption метода.

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

TCP state diagram

Состояния TCP-соединения и переходы между ними

Тут может пригодится perl-утилитка под названием killcx, которая должна помочь и в случае когда TCP-соединение пребывает в состоянии TIME_WAIT. Работает примерно так:

В качестве аргумента ей нужно передать IP-адрес и порт удаленной стороны TCP-соединения. В этом примере я подключился по SSH с клиента 10.11.12.13 на сервер с адресом 10.10.10.10. Команда выполнялась на сервере 10.10.10.10.

Для работы утилита требует наличия следующих perl-модулей:
* Net::RawIP (для создания spoofed packets, CPAN-ом он у меня просто так ставиться не захотел, жалуясь на тесты, пришлось сделать force install Net::RawIP)
* Net::Pcap (для перехвата TCP-пакетов).
* NetPacket::Ethernet (для декодирования TCP/IP-пакетов).

Также может потребоваться предварительная установка пакета libpcap-devel.

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

Попытка оборвать соединения с сервисом, запущенном на порту 62616 сервера 10.10.10.10, с клиента 10.20.20.20:

Что, в принципе, было ожидаемо. На роутере я ее пока запускать не пробовал.

Ещё есть третий вариант принудительного завершения TCP-соединения - использование утилиты tcpkill. Её преимущество в том, что ее намного проще установить (по сравнению с killcx) – достаточно просто установить пакет dsniff, в состав которого она входит. Какое именно соединение обрывать ей нужно указать с помощью BPF-выражения, формат которых знаком каждому, кто пользовался tcpdump-ом.

Здесь я подключился по SSH с хоста 192.168.1.51 на сервер 192.168.1.1 и запустил сначала команду lsof чтобы узнать порт на стороне клиента (34749). Затем передал его в качестве аргумента tcpkill-у и соединение сразу было разорвано. Следует учитывать, что tcpkill сработает только для соединения, по которому передаются хоть какие-то данные. В противном случае он просто будет висеть в ожидании следующей порции трафика.

Еще один, пожалуй, самый изящный вариант с использованием отладчика gdb. Опять поключаемся по SSH с 192.168.1.51 на 192.168.1.1 и что-то там запускаем для красоты, например такой цикл:

Читайте также: