Убить сокет в состоянии CLOSE-WAIT
SLES 10. Как в консоли можно убить такой «зависший» сокет стандартными средствами? Нагуглил только tcpkill но в системе такого нет
Ищи lsof`ом кто занял сокет и прибей его.
close-wait может оставаться после закрытия породившего процесса, ЕМНИП. Закрывается сам через некоторое время.
По теме — tcpkill должен быть в составе dsniff (в Debian так (= )
lsof и fuser и пр. не подходят, процесс убивать нельзя — он держит кучу других открытые соединения через которые идут данные, «зависло» конкретное соединение которое и надо сбросить
Нету в линуксе аналога бсдшного tcpdrop, к сожалению.
>По теме — tcpkill должен быть в составе dsniff (в Debian так (= )
Соединение, по которому нет передачи данных, убить невозможно.
Это как зомби-процесс.
tcpkill или tcpdrop это как то ведь делают?
>tcpkill или tcpdrop это как то ведь делают?
tcpkill этого не делает, потому что, при отсутствии передаваемых пакетов, не может перехватить идентификатор последовательности, который нужен для внедрения в сеанс.
tcpdrop использует особенности ядра FreeBSD, и в Linux такой программы нет.
> Нету в линуксе аналога бсдшного tcpdrop, к сожалению.
Источник
Как ПРАВИЛЬНО закрывать сокеты и не только. Руководство.
На форуме не раз поднимался вопрос о правильном закрытии сокетов,
и я решил разместить небольшой труд об этом и дать ссылку на ОЧЕНЬ хороший
документ о 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,
а более опытным поможет избежать ошибок и недоразумений.
ЗЫ. Не ищите команду un_bind(), её не существует 😉
Источник
Сокеты в ОС 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 протоколы. Примеры сценариев использования, которые, по мнению автора, наиболее интересны:
перенаправление входящих/исходящих запросов;
трансляция данных на экран в шестнадцатеричном формате.
Опробуем операции в действии. Задача будет состоять в том, что необходимо отправить 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 февраля.
Источник
Как полностью уничтожить соединение сокета в C
Я сделал чат-клиент в linux с помощью сокета, и я хочу полностью уничтожить соединение. Ниже приведены соответствующие части кода:
но закрыть (носок) , похоже, не закрывает полностью уничтожить соединение, потому что после перехода на «метку» код выходит, показывая сообщение об ошибке
это соединение не происходит снова. В чем может быть проблема? Спасибо заранее.
EDIT: что я на самом деле хочу, когда я запускаю скрипт с самого начала после уничтожения соединения, он должен работать как новая программа. Как я могу это сделать?
5 ответов
на close вызов только отмечает, что TCP-сокет закрыт. Он больше не используется процессом. Но ядро может по-прежнему удерживать некоторые ресурсы в течение периода (TIME_WAIT, 2MLS и т. д.).
настройка SO_REUSEADDR должна устранить проблемы привязки.
поэтому убедитесь, что значение true действительно ненулевой при вызове setsockopt (ошибка переполнения может перезаписать его):
здесь pid переменная код. Если вы используете fork (для начиная связь обработка процессов), то вы должны закрыть sock также в процессе, который в этом не нуждается.
сначала для именования, поэтому мы все называем одни и те же вещи одинаково:
сокет перешел в listen() а потом accept() назовем слушающего сокета. Сокет, возвращенный accept() давайте вызовем принятый сокет.
на стороне клиента:
сокет перешел в connect() давайте вызовем соединительный / подключенный сокет.
по поводу Вашего вопроса:
о прекращении accept() ed связи закройте принятый сокет (то, что вы называете подключенным), сначала используя shutdown() следовал по close () . Чтобы затем принять новый цикл соединения прямо перед вызовом accept() , не через bind() и listen() снова.
только выключение и закрыть сокет, если вы хотите избавиться от до connect() s выдается после accept() вернулся.
соединение все еще активно, потому что вы забыли закрыть подключенный сокет. Закрытие слушающего сокета не автоматическое закрытие сокета.
Я не уверен, хотя, почему вы получаете EADDRINUSE. Код отлично работал как на linux, так и на mac os.
Источник