说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

用Delphi实现NetBIOS广播收发

HTML文档下载 WORD文档下载 PDF文档下载
用Delphi实现NetBIOS广播收发

NetBIOS网络协议对于很多读者来说可能比较陌生,但其实它是由IBM开发的一个很古老的协议,当年在LAN上也风光一时。说它老,其实也不过10年光景,IT业的发展实在是太快。由于NetBIOS不具备路由功能,也就是说它的数据包无法跨网段传输,因此在广域网、城域网大行其道的今天,它已退居配角。如果你有心的话,能够发现在Window95/98的网络协议中仍然保留着NetBIOS,不过它已经改名叫NetBEUI(NetBIOS扩展用户接口),是NetBIOS的Microsoft改进版。另外在TCP/IP以及IPX/SPX协议中,也依然保留了对NetBIOS的支持,只要查看网络协议属性中的高级,就能看到启用NetBIOS的选项。

之所以这样是有原因的。NetBIOS协议短小精悍,非常适用于小型局域网,特别是一些对实时性要求较高的网络环境。NetBIOS的广播功能由于有开发使用方便、系统开销小的优点,所以在很多场合仍然被大量使用。笔者由于工作需要,在一个航天测控软件的编制中就使用了NetBIOS广播功能。

我原以为这是件很简单的工作,因为WIN32API中提供了一个Netbios函数,里面封装了所有函数和数据结构,用起来很方便,在BC和VC下都如此。可是由于这次是使用流行的Delphi作编译器,却遇到了意想不到的麻烦:号称全面移植WIN32API的Dlphi中偏偏没有Netbios函数!这下顿时让我方寸大乱。怎么办?总不能从底层干起吧?而且时间也不允许。在冷静下来之后,我忽然想到,既然WIN95支持NetBIOS,那么系统就一定会提供DLL支持,编译器本身是没有底层支持的。于是我在机器中搜索,果然,在SYSTEM目录下有一个Netbios.dll,用快速查看将其打开,在导出表部分显示如下:

导出表:

序数 入口 名称

0000 00001a37 NetbiosAddthd

0001 000019eb NetbiosDelete

0002 00001a96 NetbiosDelthd

0003 000019b1 NetbiosInitialize

0004 0000186b PostRoutineCaller

0005 0000102e _Netbios

注意到那个0005号_Netbios导出函数了吗?那就是我需要的!经过紧张的试验调试,证明它和WIN32API手册上的Netbios完全一样。剩下的工作就比较简单了,定义一个NCB(Netbios控制块)记录,将NCB数据结构封装在里面;声明一个后处理例程以及消息处理过程,以完成广播数据的接收和发送。有关NCB数据结构的详细内容以及NetBIOS广播的原理,限于篇幅我就省略了。需要的朋友可以查看BC或VC的Help或相关书籍。下面是有关的Delphi源代码。

/////////Netbios单元///////////

unit netbios;

interface

uses windows,messages,Forms,SysUtils;

type

{$X+}{$A+}

//声明一个NCB记录指针。

PNCB=^NCB;

//声明一个后处理例程的过程类型。

POST=procedure(var ncbR:PNCB);

//以下是NCB记录,教训1:将上面的编译选项置为{$A+}以取消数据对齐。如果在广播中有浮点数的话,数据对齐会让你大吃苦头!我已经有过惨痛教训!:(

NCB=record

ncb_command:UCHAR;

ncb_retcode:UCHAR;

ncb_lsn:UCHAR;

ncb_num:UCHAR;

ncb_buffer:PCHAR;

ncb_length:WORD;

ncb_callname:array [1..16] of UCHAR;

ncb_name:array [1..16] of UCHAR;

ncb_rto:UCHAR;

ncb_sto:UCHAR;

ncb_post:POST;

ncb_lana_num:UCHAR;

ncb_cmd_cplt:UCHAR;

ncb_reserve:array [1..10] of UCHAR;

ncb_event:HANDLE;

end;

//声明自己的Netbios函数。教训2:一定要使用pascal调用规范,否则,嘿嘿!!

function NetbiosSR(ncbX:PNCB):UCHAR;pascal;

//初始化NCB。

procedure InitNCB(var ncbY:PNCB);

//后处理例程,注意使用远指针。

procedure postrout(var ncbR:PNCB);stdcall;far;

var

char_buffer:array[0..511]of UCHAR;

int_buffer:array[1..512]of Byte;

implementation

//调用系统的Netbios。dll中的Netbios函数标号是6。Delphi搜索外部文件的顺序是当前目录→系统目录→其他目录,别忘了保证存在Netbios.dll。

function NetbiosSR(ncbX:PNCB):UCHAR;external ‘netbios' index 6;

procedure InitNCB(var ncbY:PNCB);

var

x:integer;

begin

ncbY.ncb_command:=0;

ncbY.ncb_retcode:=0;

ncbY.ncb_lsn:=0;

ncbY.ncb_num:=0;

ncbY.ncb_length:=512; //数据缓冲长度,最大512B。

for x:=1 to 16 do

begin

ncbY.ncb_callname[x]:=0;

ncbY.ncb_name[x]:=0;

end;

ncbY.ncb_rto:=0;

ncbY.ncb_sto:=0;

ncbY.ncb_lana_num:=0;

ncbY.ncb_cmd_cplt:=0;

for x:=1 to 10 do

ncbY.ncb_reserve[x]:=0;

ncbY.ncb_event:=0;

end;

//后处理例程的作用是当接收到广播消息时,立即向相应窗口发送消息。我在这里偷了点懒,以广播方式发送一个定时器消息。如果你愿意可以向指定窗口发送自定义消息,这样要复杂一些。首先,要把指定窗口的句柄传递给后处理例程。通常这是做不到的,但可以利用一些技巧做到。在NCB记录后面紧挨着声明一个句柄类型,然后把指定窗口的句柄赋值给它的实例变量;这样句柄变量的地址与NCB是连续的。在后处理中通过指针或汇编语句将ncbR的地址移到最后一个字节+1,就是窗口句柄的起始地址。明白吗?至于自定义消息,需要重新编译连接库,限于篇幅我就不罗嗦了,有兴趣的可以自己尝试。

procedure postrout(var ncbR:PNCB);

begin

sendMessage(wnd_BROADCAST,WM_TIMER,0,0);

end;

end.

////////窗口单元//////////

unit broadcast;

interface

uses

Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,

netbios;

type

Tmain=class(TForm)

private

{Private declarations}

//消息处理过程,注意消息宏要与后处理中的一致。

procedure post_main(var Message:TMessage);message WM_TIMER;

public

{Public declarations}

end;

var

main: Tmain;

ncbname:UCHAR;

ncbRock:PNCB;

post_add:POST;

implementation

{$R *.DFM}{$A-}{$I-}

/////////主窗口建立过程/////////

procedure Tmain.FormCreate(Sender: TObject);

var

ret:UCHAR;

i,x,y:integer;

p:single;

begin

new(ncbRock);

randomize();i:=0;

FillChar(char_buffer,sizeof(char_

buffer),0);

post_add:=@postrout;

//取后处理例程的地址。

ncbRock.ncb_buffer:=@char_buf

fer; //取数据缓冲区的地址。

InitNCB(ncbRock);

ret:=9;

ncbname:=random(100);

ncbRock.ncb_name[1]:=ncbna

me;

ncbRock.ncb_command:=$30;

//加名,ret为0加名成功。

while ((i<10)and(ret<>0)) do

begin

ret:=netbiosSR(ncbRock);

i:=i+1;

end;

if ret<>0 then

begin

for i:=1 to 20 do

messagebeep(-1);

MessageDlg(‘网络通信无法实现!您需要关闭程序重新运行.',mtWarning,

[mbOk],0);

end

else if ret=0 then

begin

ncbRock.ncb_post:=post_add;

ncbRock.ncb_command:=$a3; //异步接收方式字。

ncbRock.ncb_event:=0;

ncbRock.ncb_length:=512;

ret:=netbiosSR(ncbRock);

end;

end;

///////////广播消息处理过程/////

procedure Tmain.post_main(var Message:TMessage);

var

x:integer;

ret:UCHAR;

begin

//取出数据缓冲区的内容

for x:=0 to 511 do

int_buffer[x+1]:=char_buffer[x];

////以下可以进行数据处理////

//重新打开异步接受。

ncbRock.ncb_post:=post_add;

ncbRock.ncb_command:=$a3;

ncbRock.ncb_event:=0;

ncbRock.ncb_length:=512;

ret:=netbiosSR(ncbRock);

end;

end.

注:广播发送非常简单,不再详述。上述程序经过一年运行完全可靠。另外,经过改造可以将其改为LAN下的聊天程序。

玩转物联网之MQTT 专访都灵创客教育奚炎:被忽视的Maker教育 13岁iOS开发者:Swift开发Sprite Kit游戏实践 专访豌豆荚「自动装」开发团队:无需Root即可批量点击「下一步」 iOS项目的持续集成与管理 《近匠》谛听科技,探索智慧家庭的智能网关 【简讯】Python 3.5.0b1发布 《算法的乐趣》作者王晓华访谈:多看、多做、多想是秘诀 专访李祎:Java在Testin的技术应用 React首部经典图书推荐:全程经典实例,360度剖析React.js 再做一个Android!Google发布第二代VR眼镜Cardboard Go语言开发常见陷阱,你遇到过几个? 奏响年度最强音 第七届中国云计算大会日程全公布(表) 【CTO讲堂】请在还年轻的时候,尽量多踩些坑 以细分使用场景为突破点 探究墨迹天气的体验创新 熟练成就创造——MathWorks全球副总裁Richard Rovner、产品市场经理赵志宏专访 Objective-C编码规范:26个方面解决iOS开发问题 豌豆机器小组发布最新WRTnode2R,支持华为Liteos、QQ物联与AllJoyn [新书推荐]Node.js项目实践:构建可扩展的Web应用 【简讯】Perl 5.22.0 发布,大幅改进代码! 【征文】特别策划——群雄逐鹿共话新型数据库 针对DCloud侵权质疑,APICloud发布声明 《近匠》小鱼天气,中国风与细粒度空气质量检测 Xcode 7 beta发布,Swift 2.0带来哪些新变化? 【有奖征集】MDCC 2015演讲议题征集全面启动 Swift语言那些鲜为人知的特性 《开源者说》08期:聊聊Java那些事儿 专访唐成:从小工到专家,PostgreSQL的修炼之道 《瞬间之美》作者Robert Hoekman Jr:如何成长为UX领袖人物? TIOBE 2015年6月编程语言排行榜:Swift份额上升,Objective-C成自由落体 【CTO讲堂】Box首位华人核心工程师的回国创业之路 注册表的问题,有什么方法*****(送100分) 请问黑龙江中程成绩怎么查呀? 请问.net能在linux等操作系统上运行吗? 一个简单的问题? 请问哪里有delphi第三方控件开发和使用的书籍下载啊? 请问.net能在linux等操作系统上运行吗? 请问awt和swing有什么本质的不同呢?! 有点难度的sql 90分!看看这段JSP程序为什么出错。谢了! 模式窗体的postback 求教:在在模式对话框BOOL CXXX::OnInitDialog()中InitSocket()初始化失败,怎样退出该模式对话框 关于JTable,如何设置一行的颜色。 一个很简单的问题 读取远程的页面文件内容,但需要搜索结果的页面,请问如何实现??? 写了一个telnet服务器端程序,不能用exit退出,请大家帮忙看看~~谢谢! ?!我怎么看不了帖子内容啊?!点开每一贴都出现同样的页面如下,各位是怎样? 我只能看见标题:( 图片文件上载页,在上载页中实现预览的问题?急! 我的Asp为什么不能执行? 请教xml问题。 如何动态获得表单中checkbox中的name的值还有获得其值。 如何在UNIX下配置 Tomcat4.0 + Apache1.3 + JDK1.3? 在线等待! 请问版主:为何我在本版搜索“多语言”,找到的结果中没一个打得开? 如何在一个菜单项里控制另一个菜单项的状态(如变灰) 菜鸟问题 关于几个按钮布局?急 求救:关于在程序中运行其他程序的问题! 请问哪有Report Machine的下载? 请问只知道备份文件如何恢复数据库? To:qxjavajava: 哪里可以找到scjd的题目大家先做一下? 高程水平压线通过后的一点总结 请帮初学者看看这段简单的代码!感激t0 '_bstr_t' : missing storage-class or type specifiers 文件操作安全问题,请微软专家和各位高手进来看看 请教tdbgrid如何在非绑定模式下加入新行写入数据 问一下,在datagrid里加入comboBox控件后,怎样使comboBox的边框不可见? ==高手请看,数据库备分恢复问题== 这两种赋值方法真的有区别吗?内有代码,请指点 关于与后台连接的问题 请问黑龙江中程成绩怎么查? 如何用sql语句统计满足条件的记录数? 用ASP作下拉式菜单怎么坐呀?蛮着急的呀!! 一个看似简单实则绕脑的小问题 pb8是否内嵌easerver服务器? help 请教高手:一个写输出的问题,再线等待 我在一个组件中定义了一个Text2的属性,可如何让它显示在VS。NET的属性框中呢。 用了XTREME后,它自己生成的SDI框架中,菜单.状态栏的字体太小,我想改成9号宋体,怎么办? 怎样在数据库里保存文件! 急急。。得到树的导航?在线等待!! 刚才忘记说了,如何在sql里给中文排序? 请问有什么函数可以将BigdDecimal类型转换成为String类型??(很着急!) 来者有分 杭州东站屋顶发电站昨并网发电 可供电浙江4个普通收费公路项目今日24时提全国人均月薪杭州4595元排名第五(杭州火车南站7月1日起全封闭改扩建杭州今起出梅 一年中最热酷暑到来新老年法7月1日起实施 常回家看看被金华市唯一五星级酒店卫生检测不合格生态日杭城开展骑行活动铁路杭州南站6月30日落幕等待扩建张鸿铭任杭州市委副书记 提名为市长候买房配套利用率不高 业主争论12万改东站乘车设施不完善 网络购票需提前取杭州气象台发布高温报告 未来最高温可温州整顿行政审批搭车服务 对强制收费高铁开放五种买票方式 换乘时间要预留宁波首趟高铁列车发车17分钟时速达3杭州东站换乘有攻略 每层都设购票点宁波今明最高气温达38℃ 夏季小儿易杭州朝晖六区房屋变形 倾斜远超危房标杭州昨首发高温橙色预警 今明预计最高宁波到上海高铁昨天中午在杭州东站停靠驻贝宁大使陶卫光拜会贝宁总统亚伊驻墨西哥大使邱小琪会见墨西哥革命制度“北大仓”回归“北大荒”:中国发展的驻克罗地亚大使邓英会见海南省省委副书驻黑山大使崔志伟会见黑中友好协会主席两部门下拨蒙辽豫鄂宁2.81亿元中央国民党发言人陈以信:不动产98%已回台湾“九合一”选举11月9日编造选举特写:探访草原上最大的侵华日军要塞组团进城学科技兰西农民心欢喜澳官员帕尔默发表“辱华言论” 悉尼亚男童嫌楼外“蜘蛛人”施工太吵割断安全老年人的幸福生活:醉心“戏迷”你唱罢生饮山泉水 妇人肚中长两条蛲虫海峡两岸诗书画交流展启幕 连战吴伯雄欧洲央行选定ABS计划顾问柯震东获释在即 传被下“封口令”河南拟推旅游小费合法化美国国会预算办:预算和经济前景喜忧参江苏吴江女大学生失踪案告破 嫌疑人购悉尼亚裔社区要求帕尔默在电视上公开道
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘