![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Демонстрационный проект (VC6, MFC)
Исполняемый файл
Одно время назад у меня возникла острая необходимость заменить чем-нибудь стандартный Messenger Service. Поиск по продуктам которые дают такую возможность мало чего дал, т.к. у каждого из них была обычно какая-нибудь странная особенность к которой надо было сознательно привыкать, дабы этим продуктом пользоваться.
Естественно мысль написать чего нибудь свое так, как хочется просто уже висела в воздухе. Первые попытки найти информацию в инете каким образом это вообще происходит навели на странные мысли что с одной стороны многие пытались, но с другой не у всех получилось. А те, у кого получилось - молчат :(. И чтобы в будущем "ищущие" не попадали в такую же ситуацию, в какую попал я (связанную с дефицитом данных по этой теме), я и выкладываю то что у меня в результате получилось.
В инете было найдено что сервис поддерживает работу сразу по двум каналам - по mailslot и по netbios (точнее через SMB - Service Message Block - надстройка над Netbios).
C mailslot удалось разобраться довольно быстро и здесь я на этом останавливаться не буду – информация есть даже в MSDN, не говоря уже о разных форумах, а вот с технологией отcылки/приема сообщений через Netbios вышла загвоздка. В присутствии специального сервиса "Messenger Service" отсылать сообщение довольно просто (функцией WinApi “ NetMessageBufferSend”), но вот принимать - нет никакой возможности (сообщение принимается исключительно самим сервисом, реакцией которого был показ знакомого наверно многим Message box-а с текстом сообщения). В отсутствии же оного все теряется в тумане. Побившись немного головой "об стену" и ничего не узнав пришлось идти путем изобретателя велосипеда и открывать Америку заново. Поставив на две машины в сети по снифферу и послушав что шлют Messenger servic-ы друг другу формат сообщений удалось расшифровать (благо не такой он сложный). Естественно из этого следует что возможно что-то все-таки упущено, поэтому всем кто скачает и опробует эту программу у себя в сети большая просьба - если не работает, то сообщите пожалуйста где и что не работает (если будет возможность разобраться конечно). Я со своей стороны могу сказать что в нашей доменной сети пересылка сообщений (даже больших, хотя у Messenger Service есть ограничение на максимальный размер сообщений, это где-то около килобайта) между компьютерами c Windows 2000 и Windows NT проблем пока не встречала.
Теперь немного о формате. Формат Netbios-пакета включает в себя заголовок (32 байта), первые 4 байта которого стандартны - 0xFF,'S','M','B', а пятым байтом идет команда которую этот пакет "символизирует". Для отсылки/приема сообщений из заголовка кроме первых 4ех байт ничего больше не используется (заполняется нулями). Кроме заголовка в пакет входит само тело пакета. «Наполнение» этого тела зависит от команды
Команд ОЧЕНЬ много, предназначены они чуть ли не для всего - для передачи файлов/поиска файлов на удаленной машине и т.д. и т.п. За отсылку сообщений же отвечают четыре команды
0xd0 | Сообщение, помещающееся целиком в один пакет; в этот пакет помещается строка с именем «от кого», строка с именем «кому» и само сообщение (все три строки разделены 0-ым байтом) |
---|---|
0xd5 | Сообщение, не помещающееся целиком в один пакет, точней начало такого сообщения (информация от кого и кому). В такой пакет помещается лишь «от кого» и «кому» |
0xd7 | Сообщение, не помещающееся целиком в один пакет, кусок сообщения. Пакеты с этой командой шлются до тех пор пока не будет частями переслано все сообщение |
0xd6 | Сообщение, не помещающееся целиком в один пакет, конец сообщения. В пакете собственно ничего нет (сам пакет представляет из себя, кроме заголовка, 5 нулей) |
До приема/передачи сообщений также необходимо для начала зарегистрировать сетевое имя. в WinPopDown регистрится имя компьютера. Внутренний сетевой "ник" общающихся машин при регистрации должен обязательно заканчиваться на цифру 3 - это окончание "забито" Microsoftом специально для Messenger Service.
Полная замена сервиса должна по идее делать следующие вещи:
- обрабатывать сообщения, приходящие по mailslot (делается это довольно просто стандартными средствами WinApi работы с mailslot-ами. для отправки/приема сообщений используется слот с именем "messngr");
- регистрировать netbios alias не только по имени компьютера, но еще и по имени активного (залогиненного) пользователя в данный момент, а также по имени домена, в который этот пользователь входит (или по имени рабочей группы если доменной системы нет);
- правильно работать в ситуациях, когда на машине установлено несколько сетевых карт и/или протоколов, поверх которых возможно общение по NetBios
WinPopDown принимает и отправляет сообщения только от сетевого "ника", составленного из имени компьютера (т.к. программа имеет демонстрационный характер, цель поддерживать всё, полагающееся для «Messenger Service» не ставилась). Зато WinPopDown показывает реального отправителя сообщения (который в общем-то может легко не совпадать с тем что передано в самом сообщении; многие специализированные программы позволяют менять поле «от кого»; реальное сетевое имя отправителя так изменить невозможно и вот оно-то и показывается WinPopdown-ом)
Еще одним из ограничений WinPopDown является работа только по одному LAN-адаптеру (LANA), номер которого, если у Вас на машине установлено несколько сетевых карт или активны несколько поддерживающих Netbios протоколов, вы сможете выбрать при запуске программы. LANA – это некоторое число, характеризующее через какую сетевую карту и по какому протоколу более низкого уровня, поддерживающего Netbios, будет работать передача сообщений. Пример: если на компьютере установлено две карты, по каждой из которых можно обмениваться пакетами по Tcp-ip и NetBEUI, то для обмена сообщениями по NetBios будет доступно 4е Lana (каждому такому сочетанию системой будет присвоен определенный номер)– «Первая карта / Tcp-ip», «Первая карта / NetBEUI», «Вторая карта / Tcp-ip», «Вторая карта / NetBEUI». MSDN для Netbios-приложений, которые претендуют на независимость от количества LAN-адаптеров, рекомендуется использовать следующий подход – перенумеровать все адаптеры, затем для серверной части зарегистрировать сетевое имя на каждом адаптере и начать «слушать» сообщения на каждом LANA. Для клиентской части, также рекомендуется отправлять сообщения по каждому LANA, но при установке соединения хотя бы по одному такому каналу, запрос на соединения на других LANA должен быть отменен. Кстати, для старых операционных систем (например DOS, Windows 95) считалось что с точки зрения NetBios существует только один LANA, с номером 0, поэтому это значение в некоторых программах просто жестко прошивалось в коде программы.
ПРЕДУПРЕЖДЕНИЕ Так как эта программа работает вместо Messenger Service, то перед запуском надо этот сервис остановить. (потом можно запустить его вновь). Дело в том что при старте программа пытается зарегистрировать сетевой ник (про который было сказано выше). И так как это имя должно быть в сети уникальным то при запущенном Messenger Service эта попытка естественно не удастся (ведь тоже самое - регистрацию имени - при запуске делает сервис) |
Осталось привести коды ошибок которые могут возникать в процессе работы с Netbios в целом и при отсылке/приеме сообщений в частности. Вот они:
NRC_GOODRET | 0x00 | The operation succeeded. |
---|---|---|
NRC_BUFLEN | 0x01 | An illegal buffer length was supplied. |
NRC_ILLCMD | 0x03 | An illegal command was supplied. |
NRC_CMDTMO | 0x05 | The command was timed out. |
NRC_INCOMP | 0x06 | The message was incomplete. The application is to issue another command. |
NRC_BADDR | 0x07 | The buffer address was illegal. |
NRC_SNUMOUT | 0x08 | The session number was out of range. |
NRC_NORES | 0x09 | No resource was available. |
NRC_SCLOSED | 0x0a | The session was closed. |
NRC_CMDCAN | 0x0b | The command was canceled. |
NRC_DUPNAME | 0x0d | A duplicate name existed in the local name table. |
NRC_NAMTFUL | 0x0e | The name table was full. |
NRC_ACTSES | 0x0f | The command finished; the name has active sessions and is no longer registered. |
NRC_LOCTFUL | 0x11 | The local session table was full. |
NRC_REMTFUL | 0x12 | The remote session table was full. The request to open a session was rejected. |
NRC_ILLNN | 0x13 | An illegal name number was specified. |
NRC_NOCALL | 0x14 | The system did not find the name that was called. |
NRC_NOWILD | 0x15 | Wildcards are not permitted in the ncb_name member. |
NRC_INUSE | 0x16 | The name was already in use on the remote adapter. |
NRC_NAMERR | 0x17 | The name was deleted. |
NRC_SABORT | 0x18 | The session ended abnormally. |
NRC_NAMCONF | 0x19 | A name conflict was detected. |
NRC_IFBUSY | 0x21 | The interface was busy. |
NRC_TOOMANY | 0x22 | Too many commands were outstanding; the application can retry the command later. |
NRC_BRIDGE | 0x23 | The ncb_lana_num member did not specify a valid network number. |
NRC_CANOCCR | 0x24 | The command finished while a cancel operation was occurring. |
NRC_CANCEL | 0x26 | The NCBCANCEL command was not valid; the command was not canceled. |
NRC_DUPENV | 0x30 | The name was defined by another local process. |
NRC_ENVNOTDEF | 0x34 | The environment was not defined. A reset command must be issued. |
NRC_OSRESNOTAV | 0x35 | Operating system resources were exhausted. The application can retry the command later. |
NRC_MAXAPPS | 0x36 | The maximum number of applications was exceeded. |
NRC_NOSAPS | 0x37 | No service access points (SAPs) were available for NetBIOS. |
NRC_NORESOURCES | 0x38 | The requested resources were not available. |
NRC_INVADDRESS | 0x39 | The NCB address was not valid. |
NRC_INVDDID | 0x3b | The NCB DDID was invalid. |
NRC_LOCKFAIL | 0x3c | The attempt to lock the user area failed. |
NRC_OPENERR | 0x3f | An error occurred during an open operation being performed by the device driver. This error code is not part of the NetBIOS 3.0 specification. |
NRC_SYSTEM | 0x40 | A system error occurred. |
Напоследок - повторюсь. Т.к. все-таки информация наполовину получена эмпирическим путем, то если у вас в различных сетевых условиях будут возникать глюки - сообщите пожалуйста на каких средах они возникают: либо по emailу razinkov@mail.ru, либо сюда, в комментарии к статье
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |