Как закрыть сокет linux

Убить tcp соединение в linux

У меня есть какое-то мертвое соединение в одном приложении, которое находится в зависшем состоянии, если клиентская машина мертва.

Есть ли способ прекратить эти опции из командной строки Linux без перезагрузки сервера?

После поиска я нашел решение под названием tcpkill. Но это не сработает для меня. Так как он постоянно блокирует этот ip.

Чтобы «убить» сокет, вы должны отправить пакет сброса TCP. Чтобы отправить его (и принять другую сторону), вы должны знать фактический порядковый номер TCP.

1) Уже упомянутый tcpkill метод изучает номер SEQ путем пассивного прослушивания в сети и ожидания получения действительных пакетов этого соединения. Затем он использует полученный номер SEQ для отправки пакетов RSET обеим сторонам. Однако, если соединение неактивно / зависло и данные не передаются, оно ничего не будет делать и будет ждать вечно.

2) Другой метод использует скрипт perl, который называется killcx ( ссылка на Sourceforge ). Это активно отправляет поддельные пакеты SYN и узнает номер SEQ из ответа. Затем он отправляет пакеты RSET так же, как tcpkill .

Альтернативный подход (основанный на том, чего вы хотите добиться) — использовать gdb отладчик для подключения к процессу, владеющему этим сокетом / соединением, и close() выполнять системный вызов от его имени — как подробно описано в этом ответе .

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

Источник

Как ПРАВИЛЬНО закрывать сокеты и не только. Руководство.

На форуме не раз поднимался вопрос о правильном закрытии сокетов,
и я решил разместить небольшой труд об этом и дать ссылку на ОЧЕНЬ хороший
документ о unix-socket (в конце).

Close() закрывает сокет, но не закрывает соединение. Поэтому, при попытке
прибайндиться к нему появляются ошибки типа «socket error: address already in use».
Сохранение соединения бывает необходимо в мультитриадных приложениях.
Рассмотрим простой пример клиента. При установлении соединения с сервером
он форкается, затем дитё (порождённый процесс) посылает на сервер вводимые
с клавы данные пока не получит EOF. При получении EOF дитё выполняет close(),
т.е. закрывает сокет (но не соединение !). А родитель по этому же соединению
может принять ответ сервера. Удобно . Таким образом при использовании сlose()
ядро не обрывает соединение, а только закрывает сокет процесса, выполнившего close().
Ядро не закроет соединение до тех пор, пока хоть один процесс прибайнден к нему.
И даже если все процессы завершатся, ядро какое-то время продержит соединение
открытым (при условии что все процессы использовали только close() ).
Ядро переведет соединение в состояние TIME_WAIT. Как долго ядро продержит
его в этом состоянии зависит от конкретной реализации стека протоколов TCP/IP.
В среднем от 30 секунд до 4 минут. И в это время к этому
адресу (паре IP адрес/порт) нельзя будет прибайндиться. При выполнении
shutdown(sock, 2) вы сообщаете ядру, что больше не намерены ни читать, ни писать
из/в соединение и ядро закрывает соединение и освобождает адрес (пару IP адрес/порт).
Теперь к этому адресу можно прибайндиться. Получается, что shutdown(sock, 2) это
что-то вроде un_bind(). Если вы завершаете процесс и больше не намерены использовать
соединение, то вы должны выполнить shutdown(sock, 2) и затем close(sock). Будьте
внимательны при выполнении shutdown(sock, 2), если вы завершаете родительский
процесс не дожидаясь завершения порожденных процессов. После этой команды НИ ОДИН
процесс, прибайнденный к этому соединению(адресу), не сможет использовать его.
Они получат EOF при попытке чтения и SIGPIPE при попытке записи (возможно с опозданием,
пока буфер сокета не будет заполнен).
Вот вобщем-то и всё. Здесь я привел вольный перевод документа, который вы можете
найти на
ftp.gigabitsale.com/pub/old_stuff/new/doc/unix-socket-faq.usenet
и на
ftp.tura.ru/pub/old_stuff/new/doc/unix-socket-faq.usenet
Очень рекомендую всем. Начинающим он поможет понять природу unix-socket,
а более опытным поможет избежать ошибок и недоразумений.

Читайте также:  Alternative rdp clients windows

ЗЫ. Не ищите команду un_bind(), её не существует 😉

Источник

Как принудительно закрыть сокет в TIME_WAIT

Я запускаю определенную программу на linux, которая иногда аварийно завершается. Если после этого быстро открыть ее, она слушает сокет 49201, а не 49200, как в первый раз. netstat показывает, что 49200 находится в состоянии TIME_WAIT.

Есть ли программа, которую можно запустить, чтобы немедленно заставить этот сокет выйти из состояния TIME_WAIT?

Ответ 1

Transmission Control Protocol (TCP) разработан как двунаправленный, упорядоченный и надежный протокол передачи данных между двумя конечными точками (программами). В данном контексте термин « надежный » означает, что он будет повторно передавать пакеты, если они будут потеряны в процессе передачи. TCP гарантирует надежность, посылая обратно пакеты подтверждения (ACK) для одного или нескольких пакетов, полученных от аналога.

То же самое относится и к управляющим сигналам, таким как запрос/ответ на завершение. RFC793 определяет состояние TIME-WAIT следующим образом:

TIME-WAIT — представляет собой ожидание достаточного времени, чтобы убедиться, что удаленный TCP получил подтверждение своего запроса на разрыв соединения.

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

Назовем первого, кто объявляет о прекращении соединения, активным замыкающим, а другого — пассивным замыкающим. Когда активный доводчик посылает FIN, состояние переходит в FIN-WAIT-1. Затем он получает ACK на отправленный FIN, и состояние переходит в FIN-WAIT-2. Получив FIN также от пассивного доводчика, активный доводчик отправляет ACK на FIN, и состояние переходит в TIME-WAIT. Если пассивный доводчик не получил ACK на второй FIN, он повторно передает FIN-пакет.

RFC793 устанавливает TIME-OUT , равным удвоенному времени жизни максимального сегмента, или 2MSL. Поскольку MSL, максимальное время, в течение которого пакет может блуждать по и нтернету, установлено в 2 минуты, 2MSL равно 4 минутам. Поскольку нет ACK на ACK, активный досылатель не может сделать ничего, кроме как подождать 4 минуты, если он правильно придерживается протокола TCP/IP, на случай, если пассивный отправитель не получил ACK на свой FIN (теоретически).

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

Чтобы ответить на вопрос дословно : « Как принудительно закрыть сокет в TIME_WAIT? » , я буду придерживаться своего первоначального ответа:

Практически говоря, я бы запрограммировал его так, чтобы он игнорировал состояние TIME-WAIT, используя опцию SO_REUSEADDR. Что именно делает SO_REUSEADDR?

Эта опция сокета сообщает ядру, что , даже если этот порт занят (находится в состоянии TIME_WAIT), все равно используйте его повторно. Если он занят, но в другом состоянии, вы все равно получите ошибку « адрес уже используется » . Это полезно, если ваш сервер был выключен, а затем сразу же перезапущен, а сокеты на его порту все еще активны. Вы должны знать, что , если поступят неожиданные данные, это может запутать ваш сервер, хотя такое маловероятно.

Ответ 2

Насколько я знаю, нет способа принудительно закрыть сокет, кроме написания лучшего обработчика сигналов в вашей программе, но есть файл /proc, который управляет временем тайм — аута. Файл имеет следующий вид:

и вы можете установить тайм-аут в 1 секунду, выполнив следующее:

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle

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

Существует также соответствующий файл:

который контролирует возможность повторного использования сокетов TIME_WAIT (предположительно без какого-либо тайм — аута).

Кстати, документация ядра предупреждает вас не изменять ни одно из этих значений без «совета/просьбы технических экспертов». Программа должна была быть написана для попытки привязки к порту 49200 и последующего увеличения на 1, если порт уже используется. Поэтому, если у вас есть контроль над исходным кодом, вы можете изменить это поведение, чтобы подождать несколько секунд и повторить попытку на том же порту, вместо инкремента.

Читайте также:  0x800f0906 windows 2012 r2

Ответ 3

Другой вариант — использовать опцию SO_LINGER с тайм-аутом 0. Таким образом, при закрытии сокета он будет закрыт принудительно, посылая RST, а не переходя в режим закрытия FIN/ACK. Это позволит избежать состояния TIME_WAIT и может быть более подходящим для некоторых случаев.

Ответ 4

Альтернативным решением может быть использование надежного прокси-сервера или программы переадресации портов, которая прослушивает порт 49200, а затем переадресует соединение на один из нескольких экземпляров вашей менее надежной программы, использующих разные порты. Например, HAPROXY.

Кстати, порт, через который вы подключаетесь, довольно высокий. Вы можете попробовать использовать неиспользуемый порт чуть выше диапазона 0-1024. Ваша система с меньшей вероятностью будет использовать более низкий номер порта в качестве него.

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

Источник

Сокеты в ОС Linux

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

Что такое сокет?

Сокет — это абстракция сетевого взаимодействия в операционной системе Linux. Каждому сокету соответствует пара IP-адрес + номер порта. Это стандартное определение, к которому привыкли все, спасибо вики. Хотя нет, вот здесь лучше описано. Поскольку сокет является только лишь абстракцией, то связка IP-адрес + номер порта — это уже имплементация в ОС. Верное название этой имплементации — «Интернет сокет». Абстракция используется для того, чтобы операционная система могла работать с любым типом канала передачи данных. Именно поэтому в ОС Linux Интернет сокет — это дескриптор, с которым система работает как с файлом. Типов сокетов, конечно же, намного больше. В ядре ОС Linux сокеты представлены тремя основными структурами:

struct socket — представление сокета BSD, того вида сокета, который стал основой для современных «Интернет сокетов»;

struct sock — собственная оболочка, которая в Linux называется «INET socket»;

struct sk_buff — «хранилище» данных, которые передает или получает сокет;

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

socket — создание сокета;

bind — действие используется на стороне сервера. В стандартных терминах — это открытие порта на прослушивание, используя указанный интерфейс;

listen — используется для перевода сокета в прослушивающее состояние. Применяется к серверному сокету;

connect — используется для инициализации соединения;

accept — используется сервером, создает новое соединение для клиента;

send/recv — используется для работы с отправкой/приемом данных;

close — разрыв соединения, уничтожение сокета.

Если о структурах, которые описаны выше, заботится ядро операционной системы, то в случае команд по управлению соединением ответственность берет на себя приложение, которое хочет пересылать данные по сети. Попробуем использовать знания о сокетах для работы с приложениями netcat и socat.

netcat

Оригинальная утилита появилась 25 лет назад, больше не поддерживается. На cегодняшний день существуют порты, которые поддерживаются различными дистрибутивами: Debian, Ubuntu, FreeBSD, MacOS. В операционной системе утилиту можно вызвать с помощью команды nc, nc.traditional или ncat в зависимости от ОС. Утилита позволяет «из коробки» работать с сокетами, которые используют в качестве транспорта TCP и UDP протоколы. Примеры сценариев использования, которые, по мнению автора, наиболее интересны:

перенаправление входящих/исходящих запросов;

трансляция данных на экран в шестнадцатеричном формате.

Читайте также:  Android ndk mac os

Опробуем операции в действии. Задача будет состоять в том, что необходимо отправить TCP данные через netcat в UDP соединение. Для лабораторной будет использоваться следующая топология сети:

Введем команду на открытие порта на машине Destination: nc -ulvvp 7878

Настроим машину Repeater. Так как передача из одного интерфейса этой машины будет происходить по протоколу TCP, а на другой интерфейс будет осуществляться передача по протоколу UDP, то для таких действий необходимо сделать соединитель, который сможет накапливать данные и пересылать их между открытыми портами. На такую роль отлично подходит FIFO файл. Поэтому команда для запуска будет выглядеть так: sudo mkfifo /tmp/repeater #создать FIFO файл
sudo nc -l -p 4545 > /tmp/repeater | nc -u 10.0.3.5 7878 IP адрес 10.0.3.5 — адрес машины Destination. Символы «|» и «> nc 10.0.2.4 4545

В итоге получаем возможность читать данные от машины Source:

В машине Destination:

Пример с трансляцией данных в шестнадцатеричном формате можно провести так же, но заменить команду на Destination или добавить еще один пайп на Repeater:

nc -l -p 4545 -o file

В результате будет создан файл, в котором можно будет обнаружить передаваемые данные в шестнадцатеричном формате:

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

socat

Инструмент, который до сих пор поддерживается и имеет весьма обширный функционал по склейке каналов для взаимодействия. Разработчиками инструмент именуется как netcat++. Ниже приведем небольшой список того что можно перенаправить через socat:

STDIO -> TCP Socket;

FILE -> TCP Socket;

TCP Socket -> Custom Application;

UDP Socket -> Custom Application;

Для повседневного использования достаточно опций, но если понадобится когда-то работать напрямую с серийным портом или виртуальным терминалом, то socat тоже умеет это делать. Полный перечень опций можно вызвать с помощью команды:

Помимо редиректов socat также можно использовать как универсальный сервер для расшаривания ресурсов, через него можно как через chroot ограничивать привилегии и доступ к директориям системы.

Чтобы комфортно пользоваться этим инструментом, нужно запомнить шаблон командной строки, который ожидает socat:

socat additionalOptions addr1 addr2

additionalOptions — опции, которые могут добавлять возможности логирования информации, управления направлением передачи данных;

addr1 — источник данных или приемник (влияет использование флага U или u), это может быть сокет, файл, пайп или виртуальный терминал;

addr2 — источник данных или приемник (влияет использование флага U или u), это может быть сокет, файл, пайп или виртуальный терминал;

Попробуем провести трансляцию данных из сокета в сокет. Будем использовать для этого 1 машину. Перед началом эксперимента стоит отметить, что особенностью socat является то, что для его корректной работы нужно обязательно писать 2 адреса. Причем адрес не обязательно должен быть адресом, это может быть и приложение, и стандартный вывод на экран.

Например, чтобы использовать socat как netcat в качестве TCP сервера, можно запустить вот такую команду:

socat TCP-LISTEN:4545, STDOUT

Для коннекта можно использовать netcat:

nc localhost 4545

При таком использовании, socat дает возможность пересылать сообщения в обе стороны, но если добавить флаг «-u», то общение будет только от клиента к серверу. Все серверные сообшения пересылаться не будут:

Настроим более тонко наш сервер, добавив новые опции через запятую после используемого действия:

socat TCP-LISTEN:4545,reuseaddr,keepalive,fork STDOUT

Дополнительные параметры распространяются на те действия, которые socat может выполнять по отношению к адресу. Полный список опций можно найти здесь в разделе «SOCKET option group».

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

Статья написана в преддверии старта курса Network engineer. Basic. Всех, кто желает подробнее узнать о курсе и карьерных перспективах, приглашаем записаться на день открытых дверей, который пройдет уже 4 февраля.

Источник

Оцените статью