Эффективное программирование TCP-IP

       

Применяйте программу Isof


| | |

В сетевом (и не только) программировании часто необходимо определить, какой Процесс открыл файл или сокет. Особенно это важно в сетевом окружении, поскольку, как было показано в совете 16, при завершении процесса, работавшего с сокетом, FIN не будет послан, если другой процесс держит этот сокет открытым.

Хотя ситуация, когда другой процесс держит сокет открытым, выглядит странно, но она часто возникает, особенно при работе в UNIX. Происходит вот что: один процесс принимает соединение и запускает другой процесс, который будет работать с этим соединением (кстати, именно это и делает inetd - совет 17). Если процесс, принявший соединение, не закроет сокет после создания процесса - потомка, то счетчик ссылок на это сокет будет равен двум. Поэтому после того как потомок закроет сокет, соединение останется открытым, и FIN не будет послан. |

Та же проблема может возникнуть и по другой причине. Предположим, что хост клиента, работавшего с созданным процессом, аварийно остановился, в результате чего потомок «завис». Такая ситуация обсуждалась в совете 10. Если процесс, принимающий соединения, завершит работу, то перезапустить его будет невозможно (если, конечно, не была задана опция сокета SO_REUSEADDR, - совет 23), так как локальный порт уже привязан к созданному процессу.

В этих и некоторых других случаях необходимо знать, какой процесс (или процессы) держит сокет открытым. Утилита netstat (совет 38) сообщает, что некоторый процесс занимает данный порт или адрес, но что это за процесс, неизвестно. В некоторых версиях UNIX для ответа на этот вопрос есть программа f stat. Виктор Абель (Victor Abell) написал свободно распространяемую программу lsof, работающую почти во всех версиях UNIX.

Примечание: Дистрибутив Isof можно получить по анонимному FTP с сайта vic.cc.purdue.edu из каталога pub/tools/unix/lsof.

lsof - это исключительно гибкая программа; руководство по ней занимает 26 печатных страниц. С ее помощью можно получить "самую разнообразную информацию об открытых файлах. Как и в случае tcpdump, предоставление единого интерфейса к нескольким диалектам UNIX - это существенное достоинство.


Рассмотрим некоторые возможности lsof, полезные в сетевом программировании. В руководстве приводится подробная информация и о других ее применениях.
Предположим, что после выполнения команды netstat -af inet (совет 38) вы обнаруживаете, что некоторый процесс прослушивает порт 6000:
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
Tcp      0    0 *.6000            *.*              LISTEN
Порт 6000 не относится к хорошо известным (совет 18), поэтому возникает вопрос: что же его прослушивает? Как уже упоминалось, в netstat по этому поводу ничего не говорится - она лишь сообщает о наличии прослушивающего процесса. Зато программа lsof не испытывает никаких затруднений:
bsd# lsof -i TCP:6000
COMMAND   PID USER FD TYPE    DEVICE SIZE/OFF NODE NAME


XF86_Mach 253 root 0u inetOxf5d98840 0t0     TCP *:6000 (LISTEN)
bsd#
Следует отметить, что вы запускали lsof от имени пользователя root. Это необходимо, потому что используемая версия lsof сконфигурирована для перечисления файлов, принадлежащих только данному пользователю, за исключением ситуации, когда ее запускает root. Это свойство направлено на обеспечение безопасности, но его можно отключить во время компиляции программы. Далее надо отмети, что процесс был запущен пользователем root с помощью команды XF86_Mach. Это ваш Х-сервер.
Опция -i TCP: 6000 означает, что lsof должна искать открытые ТСР-сокеты, привязанные к порту 6000. Можно было бы показать все ТСР-сокеты с помощью опции -i TCP или все TCP- и UDP-сокеты - с помощью опции -i.
Предположим, что вы еще раз запустили nets tat и обнаружили, что кто-то открыл FTP-соединение с хостом vie. ее. purdue. edu:
Active Internet connections
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp    0      0     bsd.1124  vie.cc.purdue.edu. ftp ESTABLISHED
Выяснить, кто это сделал, поможет lsof:
bsd# Isof -i @vic.cc.purdue.edu
COMMAND PID USER FD  TYPE              DEVICE SIZE/OFF NODE NAME
ftp     450 jcs  3u inet 0xf5d99f00    0t0  TCP bsd:1124->
 vie.cc.purdue.edu:ftp ESTABLISHED
bsd#
Как обычно, в имени машины bsd опущен домен и строка разбита на две. Из полученной выдачи видно, что FTP-соединение открыл пользователь jcs.
Необходимо подчеркнуть, что lsof может выдать информацию только об открытых файлах. Собственно говоря, название программы - аббревиатура list open files (перечислить открытые файлы). Это, в частности, означает, что с ее помощью нельзя получить информацию о TCP-соединениях, находящихся в состоянии TIME-WAIT (совет 22), поскольку с ними не связан никакой открытый сокет или файл.

Содержание раздела