II. NetBios REXX

Автор: Kádár Zsolt

Дата: 12.12.1998

Источник: https://xenia.sote.hu

Язык: Венгерский

A Lan Server, Samba, vagy más termékek által használt NetBios kommunikációs protokoll is programozható REXX-bôl, ha rendelkezünk a megfelelô bôvítô DLL-lel. Én pl. a 8-as DEVCON CD-n, a \DEVTOOLS\RXNETB könyvtárban találtam meg a REXXNETB.DLL-t, amelyben megvannak mindazon segédfüggvények, amelyek a NetBios protokoll használatához szükségesek.

A függvények regisztrálása

Mielôtt használhatnánk a DLL-ben található függvényeket, természetesen regisztrálni kell azokat. Formailag csupán egyetlen függvényt tartalmaz a DLL, amely a megadott paraméterektôl függôen különbözô feladatokat végez el. Emiatt a regisztrálás is csupán egyetlen függvénye terjed ki:

CALL RxFuncAdd 'NETBIOS','REXXNETB','NETBIOSSRV'

Magától értetôdik, hogy a REXXNETB.DLL-nek jelen kell lennie a futtatott REXX program alkönyvtárában, vagy egy olyan könyvtárban, amely benne van a LIBPATH-ban, különben a regisztrálás sikertelen lesz. A DLL azt is megengedi, hogy a függvény nevét mi magunk válasszuk meg. A név ugyanis mindig az RxFuncAdd utasítás elsô paramétere lesz. Az alapértelmezett érték NETBIOS, és mi is ezt fogjuk használni.

A NetBios függvény és paraméterei

A NetBios függvényt minimum két paraméterrel kell meghívni. Az elsô paraméter határozza meg, hogy a függvény tulajdonképpen mit is csináljon, s a további paraméterek testesítik meg a kimeneti és bemeneti adatokat:

Rc = NETBIOS( funkció [ paraméterek ] )
Call NETBIOS  funkció [ paraméterek ]

A használható funkciókat, paramétereket és visszatérési értékeket összefoglaltuk az alábbi táblázatban:

Funkció és szintakszis: Paraméterek: Visszatérési érték:
NetBios név regisztrálása: NETBIOS( 'AddName', adapter, név ) Adapter = 0, vagy 1, név = 16 bájtos NetBios karakterlánc NN YY karakterlánc, NN = visszatérési érték, YY = a névhez tartozó NetBios szám, ha NN = 0
NetBios csoportnév regisztrálása: NETBIOS( 'AddGroupName', adapter, név ) Adapter = 0, vagy 1, név = 16 bájtos NetBios karakterlánc NN YY karakterlánc, NN = visszatérési érték, YY = a névhez tartozó NetBios szám, ha NN = 0
Kapcsolat felvétele: NETBIOS( 'Call', adapter, lokális_név, partner_név, küldési_késleltetés, fogadási_késleltetés ) Adapter = 0, vagy 1, lokális_név = a kapcsolatot felvevô fél NetBios csoportneve, partner_név = a hívott fél csoportneve, küldési_késleltetés = a küldés maximális türelmi ideje (ms), fogadási_késleltetés = a fogadás maximális türelmi ideje (ms) NN YY karakterlánc, NN = visszatérési érték, YY = a létrehozott szekcióhoz tartozó NetBios szám, ha NN = 0
Pufferek kapcsolt küldése (max. 128Kb): NETBIOS( 'Chain_Send', adapter, szekció, puffer1, puffer2 ) Adapter = 0, vagy 1, szekció = Call vagy Listen által visszaadott NetBios szám, puffer1 és puffer2 = a küldendô pufferek NetBios visszatérési érték
Pufferek ellenôrzés nélküli kapcsolt küldése (max. 128Kb): NETBIOS( 'Chain_Send_NoAck', adapter, szekció, puffer1, puffer2 ) Adapter = 0, vagy 1, szekció = Call vagy Listen által visszaadott NetBios szám, puffer1 és puffer2 = a küldendô pufferek NetBios visszatérési érték
A lefoglalt NetBios erôforrások felszabadítása: NETBIOS( 'Close', adapter ) Adapter = 0, vagy 1 NetBios visszatérési érték
A beállított és az éppen nem használt NetBios erôforrások lekérdezése: NETBIOS( 'Config', adapter ) Adapter = 0, vagy 1 A visszaadott karakterlánc a következô információkat tartalmazza: beállított szekciók, beállított parancsok, beállított nevek, nem használt szekciók, nem használt parancsok, nem használt nevek
Név törlése a NetBios táblából: NETBIOS( 'DeleteName', adapter, név ) Adapter = 0, vagy 1, név = a törölni kívánt NetBios név NetBios visszatérési érték
Név keresése: NETBIOS( 'FindName', adapter, név, összetett_változó ) Adapter = 0, vagy 1, név = a keresett NetBios név, összetett_változó = a keresés eredménye (összetett_változó.0 = találatok száma, összetett_változó.1 = a csoport, vagy az egyedi név, összetett_változó.2 (vagy magasabb) = a visszaadott adat bináris formátumban NetBios visszatérési érték
A szekció bezárása: NETBIOS( 'Hangup', adapter, szekció ) Adapter = 0, vagy 1, szekció = Call vagy Listen által visszaadott NetBios szekciószám NetBios visszatérési érték
Kapcsolat felvétele: NETBIOS( 'Listen', adapter, lokális_név, partner_név, küldési_késleltetés, fogadási_késleltetés ) Adapter = 0, vagy 1, lokális_név = a hívást fogadó fél NetBios csoportneve, partner_név = a hívó fél csoportneve (* = bárki), küldési_késleltetés = a küldés maximális türelmi ideje (ms), fogadási_késleltetés = a fogadás maximális türelmi ideje (ms) NN YY karakterlánc, NN = visszatérési érték, YY = a létrehozott szekcióhoz tartozó NetBios szám, ha NN = 0
Adat fogadása: NETBIOS( 'Receive', adapter, szekció, méret, összetett_változó ) Adapter = 0, vagy 1, szekció = Call vagy Listen által visszaadott NetBios szekciószám, méret = a maximálisan küldhetô adat, összetett_változó = az összetett_változó.0-ban kerül eltárolásra a fogadott adat NetBios visszatérési érték
Adat fogadása bárkitôl: NETBIOS( 'Receive_Any', adapter, szekció, méret, összetett_változó ) Adapter = 0, vagy 1, szekció = AddName által visszaadott NetBios szekciószám, méret = a maximálisan küldhetô adat, összetett_változó = az összetett_változó.0-ban kerül eltárolásra a fogadott adat, az összetett_változó.1 tartalmazni fogja a küldô állomás nevét NetBios visszatérési érték
Körhívás fogadása: NETBIOS( 'Receive_BroadcastDatagram', adapter, szekció, méret, összetett_változó ) Adapter = 0, vagy 1, szekció = AddName által visszaadott NetBios szekciószám, méret = a maximálisan küldhetô adat, összetett_változó = az összetett_változó.0-ban kerül eltárolásra a fogadott adat, az összetett_változó.1 tartalmazni fogja a küldô állomás nevét NetBios visszatérési érték
Datagram fogadása bárkitôl: NETBIOS( 'Receive_Datagram', adapter, szekció, méret, összetett_változó ) Adapter = 0, vagy 1, szekció = AddName által visszaadott NetBios szekciószám, méret = a maximálisan küldhetô adat, összetett_változó = az összetett_változó.0-ban kerül eltárolásra a fogadott adat, az összetett_változó.1 tartalmazni fogja a küldô állomás nevét NetBios visszatérési érték
NetBios erôforrások lefoglalása: NETBIOS( 'Reset', adapter, szekciók, parancsok, nevek) Adapter = 0, vagy 1, szekciók = a lefoglalandó szekciók száma, parancsok = a lefoglalandó parancsok száma, nevek = a lefoglalandó nevek száma NetBios visszatérési érték (56 = a kért erôforrások nem elérhetôek)
Adat küldése: NETBIOS( 'Send', adapter, szekció, adat ) Adapter = 0, vagy 1, szekció = Call vagy Listen által visszaadott NetBios szám, adat = a küldendô adat NetBios visszatérési érték
Körüzenet küldése: NETBIOS( 'Send_BroadcastDatagram', adapter, szekció, adat ) Adapter = 0, vagy 1, szekció = AddName által visszaadott értél, adat = a küldendô adat NetBios visszatérési érték
Datagram küldése: NETBIOS( 'Send_Datagram', adapter, szekció, fogadó_fél, adat ) Adapter = 0, vagy 1, szekció = AddName által visszaadott értél, fogadó_fél = a partner NetBios neve, adat = a küldendô adat NetBios visszatérési érték
Adat ellenôrzés nélküli küldése: NETBIOS( 'Send_NoAck', adapter, szekció, adat ) Adapter = 0, vagy 1, szekció = Call vagy Listen által visszaadott NetBios szám, adat = a küldendô adat NetBios visszatérési érték

NetBios üzenetek fogadása

Példaképpen nézzük meg az alábbi programot, amely a REXXNETB.DLL-ben található segédfüggvény felhasználásával NetBios üzenetek fogadására és megjelenítésére képes. A program a SysSleep és a NetBios segédfüggvények regisztrálásával indul, majd pedig definiálja a NetBios szabványnak megfelelô 16 bájt hosszúságú nevet (Kliensnev). Mivel azt szeretnénk, hogy a program bárkitôl elfogadjon üzenetet, ezért a partner nevének (Szervernev) csillagot adunk meg. Ezek után lefoglaljuk a mûködéshez szükséges NetBios erôforrásokat, bejelentjük nevünket és elraktározzuk a névhez kapott azonosító számot. Ezzel gyakorlatilag készen is vagyunk, mivel most már csak várni kell, hogy valaki elkezdjen beszélni hozzánk. Amennyiben ez bekövetkezik, akkor kiíratjuk a képernyôre a kapcsolatot kezdeményezô fél nevét, s egy végtelen hurokban elkezdjük az üzenetek fogadását és képernyôre írását. Minden üzenet vételét nyugtázzuk. Amennyiben a hívást kezdeményezô QUIT üzenetet küld, akkor befejezettnek tekintjük a kapcsolatot, s várunk a következô hívásra. A példaprogram öt párbeszéd után kilép (demó verzió :-), ezt azonban könnyedén megváltoztathatjuk a megfelelô DO-loop átírásával. Figyeljük meg, hogy a hurkokba 1 másodperces szüneteket iktattunk be. Erre azért van szükség, hogy ne terheljük le feleslegesen a futtató gép processzorát.

/* NETBIOS kliens üzenetek fogadására */

/* A NETBIOS és SysSleep függvények regisztrálása */
call RxFuncAdd 'SysSleep', 'RexxUtil', 'SysSleep'
call RxFuncAdd 'netbios',  'rexxnetb', 'netbiossrv'

/* A kliens és a szerver NETBIOS neveinek definiálása */
Kliensnev  = Left('Kliens', 16, ' ')
Szervernev = Left('*', 16, ' ') /* bárki lehet */

/* Lefoglaljuk a szükséges NETBIOS erôforrásokat */
say 'A Netbios erôforrások lefoglalása folyamatban...'
Rc = netbios('Reset', 0, 1, 1, 1)
if Rc = 0 then 
  do 
     /* Bejelentjük a nevünket és kiolvassuk a hozzátartozó számot */
     parse value netbios('AddName', 0, Kliensnev) with rc name_num .
     say 'A 'space(Kliensnev)' Netbios száma: 'name_num
     say 'Várom az üzeneteket!'

     do i = 1 to 5 /* demó verzió, így csak 5 üzenetet fogadunk */
       /* Várjuk, hogy valaki üzenetet küldjön */
       parse value netbios('Listen', 0, Kliensnev, Szervernev, 0, 0) with rc lsn CallerName .

       if Rc = 0 then /* üzenet érkezik */
	 do
	    say 
	    say '�zenet érkezik! Küldô: 'space(CallerName)', Netbios száma: 'lsn
 	    do forever
		  Rc = netbios('Receive', 0, lsn, 1000, 'data.')
		  if Rc = 0 then 
		    	do
    			   say data.0 /*Kiíratjuk az üzenetet */
			   /* Nyugtázás */
      			   call netbios 'Send',0,lsn, 'A 'space(Kliensnev)' válasza: �zenetét vettem!'
			end
		  if data.0 = 'QUIT' then leave
		  call syssleep 1 /* hogy más is kapjon CPU-t */
	     end
    	    call netbios 'Hangup', 0, lsn 
	 end
       call syssleep 1 /* hogy más is kapjon CPU-t */
     end
   /* Visszaadjuk a lefoglalt Netbios erôforrásokat */
   call netbios 'Close', 0
   end
else 
  say 'A kért Netbios erôforrások nem elérhetôek (Rc = 'Rc').'

exit

NetBios üzenetek küldése

Leckénk második példaprogramja az üzenetek küldését demonstrálja. A kezdés nagyon hasonlít az elôzô példában látottakra, ugyanis regisztráljuk a szükséges segédfüggvényeket és definiáljuk a saját és a partner nevét. Lefoglaljuk az erôforrásokat és bejelentjük nevünket. Ezek után felvesszük a kapcsolatot a partnerünkkel. Amennyiben sikerült a kapcsolatfelvétel, akkor megkezdjük az üzenetek beolvasását és továbbítását. A QUIT üzenet megadásakor befejezzük a társalgást, s a lefoglalt NetBios erôforrások felszabadítása után kilépünk a programból.

/* NETBIOS szerver üzenetek küldéséhez */

/* A NETBIOS függvények regisztrálása */
call RxFuncAdd 'netbios', 'rexxnetb', 'netbiossrv'

/* A szerver és a kliens NETBIOS neveinek definiálása */
Szervernev = Left('Server', 16, ' ')
Kliensnev  = Left('Kliens', 16, ' ')

/* Lefoglaljuk a szükséges NETBIOS erôforrásokat */
say 'A Netbios erôforrások lefoglalása folyamatban...'
Rc = netbios('Reset', 0, 1, 1, 1)
if Rc = 0 then /* sikerült */
  do
     /* Bejelentjük a nevünket és kiolvassuk a hozzátartozó számot */
     parse value netbios('AddName', 0, Szervernev) with rc name_num .
     say 'A 'space(Szervernev)' Netbios száma: 'name_num

     /* Hívjuk a klienst és kiolvassuk a számát */
     parse value netbios('Call', 0, Szervernev, Kliensnev, 0, 0) with rc lsn .
     say 'A 'space(Kliensnev)' Netbios száma: 'lsn

     if Rc = 0 then /* megtaláltuk */
	do
	   do forever
	     say
	     say 'Adja meg a küldendô üzenetet! (QUIT = kilépés)'
	     pull string 
	     if string = '' then iterate

	     say 'Küldöm a következô üzenetet:' string', Címzett: 'space(Kliensnev)
	     /* Elküldjük az üzenetet a kliensnek */
    	     Rc = netbios('Send', 0, lsn, string)
	     if string = 'QUIT' then leave

	     if Rc = 0 then /* sikerült */
		do
		   /* Várjuk a kliens válaszát */
      		   Rc = netbios('Receive', 0, lsn, 1000, 'data.')
      		   if Rc = 0 then /* megjött */
       			say data.0
      		   else 
			say 'A 'space(Kliensnev)' nem válaszol (Rc = 'Rc').'
    		end
    	     else 
		say 'A küldés sikertelen volt (Rc = 'Rc').'
	   end /* forever */
           
        /* Bezárjuk a szekciót */
	call netbios 'Hangup', 0, lsn 
	end
     else
	  say 'A 'space(Kliensnev)' nincs a vonalban!!!'

     /* Visszaadjuk a lefoglalt Netbios erôforrásokat */
     call netbios 'Close', 0
  end
else 
  say 'A kért Netbios erôforrások nem elérhetôek (Rc = 'Rc').'

exit

A bemutatott két program kiválóan alkalmas arra, hogy üzeneteket továbbítsunk olyan gépek között, amelyeken telepítve van a NetBios protokoll és a hálózaton keresztül össze vannak kapcsolva. A programok módosításával azt is elérhetjük, hogy a TCP/IP protokollal mûködô talk program NetBios protokollt beszélô változatát állítsuk elô.

 

REXX GYÍK:

K1. Nem futnak gépemen a megadott példaprogramok, mert indítás után a következô üzenetet kapom:

A Netbios erôforrások lefoglalása folyamatban...
    12 +++   rc = netbios('Reset', 0, 1, 1, 1);
REX0043: Error 43 running lecke02b.cmd, line
12: Routine not found

V1. Valószínûleg nincs a gépen telepítve a NetBios protokoll, ezért nem sikerül a netbios függvény regisztrálása. A NetBios protokollt az MPTS programban lehet telepíteni.

 

Gyakorlatok:

1. Írja át a fenti példaprogramokat oly módon, hogy a hívó és a hívott felek nevét a parancssorban lehessen megadni!

2. Írja át a fenti példaprogramokat oly módon, hogy mindkettô képes legyen üzenetek fogadására és küldésére (magyarul készítsünk talk programot)!

Kádár Zsolt
1998. 12. 12.