如何利用netbios开发client/server程序 (200分)

K

kuikui

Unregistered / Unconfirmed
GUEST, unregistred user!
我写拉一个简单的listen和call程序,初始化都成功,但相互收发数据不行,请教高手!
unit dialoglisten;
interface
uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
StdCtrls, Buttons, ComCtrls,NB30;
const
MAX_SESSIONS = 10;
MAX_NAMES = 20;
MAX_LANA = 10;
MAX_BUFFER = 1024;
SERVER_NAME = 'SERVEB';
CLIENT_NAME = 'CLIENB';
CM_DataToWindow = WM_USER + 50;
type
pBufferData = ^TBufferData;
TBufferData = record
Data : array[0..MAX_BUFFER-1] of CHAR;
end;
TFmMainListen = class(TForm)
Label1: TLabel;
Label2: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Send: TBitBtn;
Clear: TBitBtn;
Label3: TLabel;
Label4: TLabel;
Edit3: TEdit;
Edit4: TEdit;
Initializelisten: TBitBtn;
StatusBar1: TStatusBar;
Reset: TBitBtn;
Edit5: TEdit;
Edit6: TEdit;
Label5: TLabel;
Label6: TLabel;
Edit7: TEdit;
Label7: TLabel;
Label8: TLabel;
Edit8: TEdit;
BitBtn1: TBitBtn;
procedure SendClick(Sender: TObject);
procedure ClearClick(Sender: TObject);
procedure InitializelistenClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ResetClick(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
//消息处理过程,注意消息宏要与后处理中的一致。
procedure CMDataToWindow(var Msg: TMsg); Message CM_DataToWindow; {处理窗口收数据消息}
procedure InitNCB(var ncbY:pNCB);
public
{ Public declarations }
function LanaEnum(Lana_enum : PLanaEnum):integer;
function ResetAll(Lana_enum : PLanaEnum;ucMaxSession,ucMaxName,bFirstName : byte):integer;
function AddName(Lana : char;name : string;num : char):integer;
function SendData(Lana,lsn : char;len : word):integer;
function ReceiveData(Lana,lsn,num : char):integer;
function ServerListen(Lana : char;name,callname : string):integer;
function SessionHangup(Lana,lsn : char):integer;
function SessionCancel():integer;
function DeleteName(lana : char;name : string):integer;
function SendSess(Lana,lsn : char;len : word):integer;
end;
//后处理例程,注意使用远指针。
procedure postrout(var g_ncbRock:pNCB);stdcall;far;
var
FmMainListen: TFmMainListen;
g_ncbRock : PNCB;
post_add : TNCBPostProc;
StartReceive : pBufferData;
pLEnum : PLanaEnum;
ncb_num,ncb_lsn : char;
in_buffer : array[0..511]of UCHAR;
out_buffer : array[0..511]of UCHAR;

implementation
{$R *.dfm}
procedure postrout(var g_ncbRock:pNCB);
begin
PostMessage(FmMainListen.Handle,CM_DataToWindow,0,0);
end;

procedure TFmMainListen.InitNCB(var ncbY:pNCB);
var
x:integer;
begin
ncbY.ncb_command := char(0);
ncbY.ncb_retcode := char(0);
ncbY.ncb_lsn := char(0);
ncbY.ncb_num := char(0);
// ncbY.buffer
ncbY.ncb_length:=512; //数据缓冲长度,最大512B。
for x:=0 to 15 do begin
ncbY.ncb_callname[x] := char(0);
ncbY.ncb_name[x] := char(0);
end;
ncbY.ncb_rto := char(0);
ncbY.ncb_sto := char(0);
// ncbY.post
ncbY.ncb_lana_num:= char(0);
ncbY.ncb_cmd_cplt:= char(0);
for x:=1 to 10 do ncbY.ncb_reserve[x]:= char(0);
ncbY.ncb_event:=0;
end;

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

function TFmMainListen.SendSess(Lana,lsn : char;len : word):integer;
var
retcode : integer;
ncbRock : PNCB;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := char(NCBSENDNA);// or ASYNCH);
ncbRock.ncb_buffer := @out_buffer; //
ncbRock.ncb_length := len;
ncbRock.ncb_lana_num:= Lana;
ncbRock.ncb_lsn := lsn;
// post_add := @postrout; //取后处理例程的地址
// ncbRock.ncb_post := post_add;

retcode := byte(Netbios(ncbRock));

if retcode = 0 then begin
StatusBar1.Panels[1].Text := 'Send Data OK!';
end
else StatusBar1.Panels[1].Text := 'Send Data Fail!';

SendSess := retcode;
Dispose(ncbRock);
end;

function TFmMainListen.DeleteName(lana : char;name : string):integer;
var
ncbRock : PNCB;
i : integer;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := char(NCBDELNAME);
ncbRock.ncb_lana_num := lana;
for i := 0 to 5 do ncbRock.ncb_name := name[i+1];
for i := 6 to 15 do ncbRock.ncb_name := #32;
if (byte(Netbios(ncbRock)) <> NRC_GOODRET) then begin
DeleteName := byte(ncbRock.ncb_retcode);
StatusBar1.Panels[3].Text := 'Delete Name Fail!';
end
else begin
DeleteName := byte(NRC_GOODRET);
StatusBar1.Panels[3].Text := 'Delete Name OK!';
end;

Dispose(ncbRock);
end;

function TFmMainListen.SessionCancel():integer;
var
ncbRock : PNCB;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := char(NCBCANCEL);
ncbRock.ncb_buffer := pchar(g_ncbRock);
ncbRock.ncb_lana_num:= g_ncbRock.ncb_lana_num;
if (byte(Netbios(ncbRock)) <> NRC_GOODRET) then SessionCancel := byte(ncbRock.ncb_retcode)
else SessionCancel := byte(NRC_GOODRET);
Dispose(ncbRock);
end;

function TFmMainListen.SessionHangup(Lana,lsn : char):integer;
var
ncbRock : PNCB;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := char(NCBHANGUP);//#146;//$92;
ncbRock.ncb_lsn := lsn;
ncbRock.ncb_lana_num:= Lana;

SessionHangup := byte(Netbios(ncbRock));

Dispose(ncbRock);
end;

function TFmMainListen.ServerListen(Lana : char;name,callname : string):integer;
var
i : integer;
ret : UCHAR;
begin
g_ncbRock.ncb_command := char(NCBLISTEN or ASYNCH);//#145; //$91
g_ncbRock.ncb_lana_num:= Lana;
for i := 0 to 5 do g_ncbRock.ncb_name := name[i+1];
for i := 6 to 15 do g_ncbRock.ncb_name := #32;
for i := 0 to 5 do g_ncbRock.ncb_callname := callname[i+1];
for i := 6 to 15 do g_ncbRock.ncb_callname:= #32;
post_add := @postrout; //取后处理例程的地址
g_ncbRock.ncb_post := post_add;

ret := byte(Netbios(g_ncbRock));

if ret <> 0 then begin
StatusBar1.Panels[0].Text := 'Server Listen Fail!';
ServerListen := byte(g_ncbRock.ncb_retcode);
end
else begin
ncb_lsn := g_ncbRock.ncb_lsn;
ServerListen := $0;
end;
end;

function TFmMainListen.ReceiveData(Lana,lsn,num : char):integer;
var
ncbRock : PNCB;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := char(NCBRECV or ASYNCH);//95);
ncbRock.ncb_buffer := @in_buffer; //取数据缓冲区的地址。
ncbRock.ncb_length := sizeof(in_buffer);
ncbRock.ncb_lana_num:= Lana;
ncbRock.ncb_lsn := lsn;
ncbRock.ncb_num := num;
if byte(Netbios(ncbRock)) <> $0 then begin
StatusBar1.Panels[1].Text := 'Receive data error!';
ReceiveData := byte(ncbRock.ncb_retcode);
end
else begin
StatusBar1.Panels[1].Text := 'Receive data OK!';
ReceiveData := ncbRock.ncb_length;
end;
Dispose(ncbRock);
end;

function TFmMainListen.SendData(Lana,lsn : char;len : word):integer;
var
retcode : integer;
ncbRock : PNCB;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := char(NCBSEND);// or ASYNCH);//#148;// $94
ncbRock.ncb_buffer := @out_buffer; //
ncbRock.ncb_length := len;//sizeof(out_buffer);
ncbRock.ncb_lana_num:= Lana;
ncbRock.ncb_lsn := lsn;

retcode := byte(Netbios(ncbRock));

if retcode = 0 then begin
StatusBar1.Panels[1].Text := 'Send Data OK!';
end
else StatusBar1.Panels[1].Text := 'Send Data Fail!';

SendData := retcode;
Dispose(ncbRock);
end;

function TFmMainListen.AddName(lana : char;name : string;num : char):integer;
var
i : integer;
ncbRock : PNCB;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := char(NCBADDNAME);//#176; //$B0
ncbRock.ncb_lana_num:= lana;
// strPCopy(ncbRock.ncb_name,name);
for i := 0 to 5 do ncbRock.ncb_name := name[i+1];
for i := 6 to 15 do ncbRock.ncb_name := #32;

i := byte(Netbios(ncbRock));
if i <> 0 then begin
StatusBar1.Panels[0].Text := 'Add name error!';
AddName := byte(ncbRock.ncb_retcode);
end
else begin
ncb_num := ncbRock.ncb_num;
AddName := $0;
end;
Dispose(ncbRock);
end;

function TFmMainListen.ResetAll(Lana_enum : PLanaEnum;ucMaxSession,ucMaxName,bFirstName : byte):integer;
var
i : integer;
ncbRock : PNCB;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := char(NCBRESET);
ncbRock.ncb_callname[0] := char(ucMaxSession); //Query of max sessions
ncbRock.ncb_callname[1] := #0; // Query of max NCBs (default)
ncbRock.ncb_callName[2] := char(ucMaxName); // Query of max names
ncbRock.ncb_callName[3] := char(bFirstName); // Query of use NAME_NUMBER_1
ncbRock.ncb_lana_num := char(Lana_enum.lana[0]);
i := byte(Netbios(ncbRock));
if i <> 0 then begin
StatusBar1.Panels[0].Text := 'Reset All error!';
ResetAll := byte(ncbRock.ncb_retcode);
end
else ResetAll := $0;
Dispose(ncbRock);
end;

function TFmMainListen.LanaEnum(Lana_enum : PLanaEnum):integer;
var
ncbRock : PNCB;
ret : integer;
begin
New(ncbRock);
InitNCB(ncbRock); //Initialize
ncbRock.ncb_command := Char(NCBENUM); //NCBENUM = $37; Nb30.pas
ncbRock.ncb_buffer := pchar(Lana_enum);
ncbRock.ncb_length := 512;//sizeof(Lana_enum); ???

ret := byte(Netbios(ncbRock));
if ret <> 0 then begin
StatusBar1.Panels[0].Text := 'LanaEnum no Right!';
LanaEnum := byte(ncbRock.ncb_retcode);
end
else LanaEnum := 0;
Dispose(ncbRock);
end;

procedure TFmMainListen.CMDataToWindow(var Msg: TMsg);
var
ret : UCHAR;
x,i,len : integer;
tempstr : string;
begin
ret := 9;
len := 512;

if (g_ncbRock.ncb_retcode > #0) and (g_ncbRock.ncb_retcode < #255) then Exit
else begin
////以下可以进行数据处理////
tempstr := '';
for x := 0 to 511 do tempstr := tempstr+InttoStr(byte(in_buffer[x]));
Edit4.Text := tempstr;
StatusBar1.Panels[2].Text := 'Receive data!';
end;

(* g_ncbRock.ncb_length <> 0 then begin
////以下可以进行数据处理////
tempstr := '';
for x := 0 to 511 do tempstr := tempstr+InttoStr(byte(in_buffer[x]));
Edit4.Text := tempstr;
StatusBar1.Panels[2].Text := 'Receive data!';
end; *)

ret := ServerListen(pLEnum.lana[0],SERVER_NAME,CLIENT_NAME);


//重新打开异步接受。
// g_ncbRock.ncb_post := post_add;
g_ncbRock.ncb_command := char(NCBRECV or ASYNCH);

g_ncbRock.ncb_buffer := @in_buffer;
g_ncbRock.ncb_length := sizeof(in_buffer);

g_ncbRock.ncb_lsn := ncb_lsn;
g_ncbRock.ncb_num := ncb_num;
g_ncbRock.ncb_lana_num:= pLEnum^.lana[0];
// ncbRock.ncb_event := 0;
ret:=byte(netbios(g_ncbRock));
end;

procedure TFmMainListen.SendClick(Sender: TObject);
var
ret:UCHAR;
i,x,len:integer;
tempstr : string;
ncbRock : PNCB;
begin
New(ncbRock);
len := 512;
i := Length(Edit3.Text);
if i <> 0 then begin
tempstr := Edit3.Text;
for x := 0 to i do out_buffer[x] := byte(tempstr[x+1]);
for x := i+1 to 511 do out_buffer[x] := 0;

SendData(pLEnum^.lana[0],ncb_lsn,len);

end;
Dispose(ncbRock);
end;

procedure TFmMainListen.ClearClick(Sender: TObject);
begin
Edit3.Clear;
Edit4.Clear;
StatusBar1.Panels[1].Text := '';
StatusBar1.Panels[2].Text := '';
end;

procedure TFmMainListen.InitializelistenClick(Sender: TObject);
begin
if LanaEnum(pLEnum) <> $0 then exit;
Edit5.Text := InttoStr(byte(pLEnum.lana[0]));
Edit8.Text := InttoStr(Byte(pLEnum.length));

if ResetAll(pLEnum,MAX_SESSIONS,MAX_NAMES,0) <> $0 then exit;

if AddName(pLEnum^.lana[0],SERVER_NAME,ncb_num) <> $0 then exit;
Edit7.Text := InttoStr(byte(ncb_num));

end;

procedure TFmMainListen.FormCreate(Sender: TObject);
var
i : integer;
begin
GetMem(G_ncbRock,sizeof(PNCB));
New(StartReceive);
for i := 0 to MAX_BUFFER-1 do StartReceive^.Data := #0;
InitNCB(g_ncbRock);
New(pLEnum);
pLEnum^.length := '0';
for i := 0 to MAX_LANA do pLEnum^.lana := '0';
FillChar(in_buffer,sizeof(in_buffer),0);
FillChar(out_buffer,sizeof(out_buffer),0);
FillChar(StartReceive,sizeof(StartReceive),0);

Edit1.Text := SERVER_NAME;
Edit2.Text := CLIENT_NAME;
end;

procedure TFmMainListen.ResetClick(Sender: TObject);
begin
DeleteName(pLEnum^.lana[0],SERVER_NAME);
SessionHangup(pLEnum^.lana[0],ncb_lsn);
end;

procedure TFmMainListen.BitBtn1Click(Sender: TObject);
var
ret:UCHAR;
begin
ret := ServerListen(pLEnum.lana[0],SERVER_NAME,CLIENT_NAME);
Edit6.Text := InttoStr(byte(ncb_lsn));

if ret <> $0 then begin
messagebeep(MB_ICONEXCLAMATION);
StatusBar1.Panels[0].Text := 'Server Listen Fail!';
exit;
end
else if ret=0 then StatusBar1.Panels[0].Text := 'Server Listen OK!';

// while 1 = 1 do sleep(5000);
end;

end.
 
这个应该可以帮你
http://telecom.chinabyte.com/20010410/168842.shtml
 
to szf:
看过,可我的就是不行,无知道问题出在哪儿?
 
不能用TCP/UDP来做吗?
 
to 张无忌:
因为SERVER端是DOS平台下开发的,已经稳定运行,只有改CLIENT端拉。你有什么好
办法吗?
另外,DOS下的TCP/IP公开软件包也难找呀。
 
恩,NETBIOS确实不错,但是资料难找,《WINDOWS网络编程技术》上有些资料,找来看看
 
还是不行呀,有没有人可以帮忙呀?
 
<栽录自 一个站点,具体的名字我忘了,不好意思,这里对那些主动公布自己代码的同好表示感谢>


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的Delphi中偏偏没有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_buffer; //取数据缓冲区的地址。
   InitNCB(ncbRock);
   ret:=9;
   ncbname:=random(100);
   ncbRock.ncb_name[1]:=ncbname;
   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下的聊天程序。
 
网上广为流传,调试过这个程序,根本就不通,可能程序不全。
首先:使用NETBIOS都要做LanaEnum()--获得网络LANA号以及ResetAll()--初始化LANA号
其次:才是AddName()--增加网络名
最后:Listen()或者Call()
还有:HangUp()或者Cancel()或者FindName()等等。。。

我虽然有以上过程,可就是不通,可能我Pascal写得不好,再次请教高手!急!
 
kuikui, 终于找到同志了,我也正在做用基于netbios的通信,不过方法和你不同,是自己
写了个dll文件,现在listen和call都已经实现了,而且也可以互相发送接收数据了。不过
现在郁闷的是以前做的都成功了,可是前天开始在重新来用就有的行有的不行了。如果可以
就联系我吧。QQ:33847540
 
哦,再问你个问题,你call完最后结束会话的时候用不用删除名?我现在就是删除名出了
问题,下位机到是收到命令了,可是再增加名就提示15号错误,15号错误是什么知道吗?
 
返回值是15表示“Name not found”!

结束会话是不是要先挂机HangUp()?再增加名字是不是要做FindName()?
 
我以前结束会话没有用挂起就可以,可是现在有不用挂起都不行了:(增加名我到是什么
也没做。因为我的环境是一对一的。
 
求教大家指点: 现在主要问题如下:
开发的C/S程序在一台电脑中通过NETBIOS可以连接,两台电脑之间连不上?返回错误号14。
 
你的程序是根据《windows网络编程技术》中附的C++源码改变过来的吗?
 
To gauss:
没错阿,是改过来的,你有什么好的建议吗?
 
顶部