⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readme.doc

📁 一个演示使用ipx协议在局域网来传递包的例子
💻 DOC
📖 第 1 页 / 共 2 页
字号:
Using The IPX Network Protocol
==============================

This document describes the purpose of the files RIPX.H, RIPX.C and
CHAT.C and how they use IPX to transmit packets over a local area
network. Firstly, many thanks must go to Daniel Parnell
(daniel@bunyip.ph.rmit.oz.au) for his general info on IPX programming
and background (See Below).

To use IPX you must obviously have a network card and the necessary
drivers. The IPX driver PDIPX.COM interfaces with your network card via
something called a 'packet driver'. For example, I use a 3COM card and
to set up IPX I must first load the 3C5X9PD.COM packet driver and then
the PDIPX.COM driver. You'll need to refer to your network card docs to
identify the relevant driver, etc. BTW, I've only tested these routines
from DOS. If you try running from Windows 3.x/95 I'm not sure what the
results will be.

All routines should be re-compiled using the LARGE memory model. If you
are looking to use protected mode then you should try and find a file
called IPXPMODE.ZIP. I haven't included my protected mode version 'cos I
use the underestimated Symantec C/C++ compiler which comes with its own
DOS extender. This differs quite markedly from the 'normal' Watcom
compiler. IPXPMODE.ZIP is based on using Watcom though.

If you find these routines useful, drop me a line.

CyberFrog 8:)   (RoccoLoscalzo@compuserve.com)

*************************************************************************
         IIIIII   PPPPPP     XX         XX
           II     PP    PP    XX       XX
           II     PP    PP     XX     XX
           II     PP    PP      XX   XX
           II     PP    PP       XX XX
           II     PPPPPP          XXX
           II     PP             XX XX
           II     PP            XX   XX
           II     PP           XX     XX     How to send IPX packets over a
           II     PP          XX       XX    network by Daniel Parnell
         IIIIII   PP         XX         XX   s921878@minyos.xx.rmit.oz.au
                                             daniel@bunyip.ph.rmit.oz.au

                                             Started : 29th March     1994
                                             Last Mod:  2nd September 1994

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=


  On March 24th 1994 I managed to send my first IPX packet.  This was a very
exciting moment for me as it opened up a vast number of applications that
were before closed to me.  NETWORKED GAMES!!!  :)    This document attempts
to guide the would be IPXer in the techniques of sending IPX packets.
Admittedly, it has only been 5 days since my first sucessful packet, but in
that short time I have developed a set of routines that seem to work quite
well.  :)   These routines are included in appendix A and an example program
is included in appendix B.  These routines are written in Turbo Pascal 6.0,
but should be reasonably portable to other languages.

  First of all, a little background.  IPX is a protocol that allows packets
of information to be sent over a network.  These packets can be sent from one
machine to another or sent to all machines (nodes).  Sending a packet to all
machines is called a BROADCAST.  A broadcast will usually be confined to just
the local network, however there are ways around this which I will not go
into here.  ;)  These packets have a specific structure which is shown in
figure 1.

                        Figure 1 - The IPX header
   ------------------------------------------------------------------------
   | Name          | Size (bytes) | Description                           |
   ----------------|--------------|---------------------------------------|
   |Check          | 2 bytes      | Bigendian check sum                   |
   |Length         | 2 bytes      | Bigendian length of packet            |
   |tc             | 1 byte       | Transport control (age of packet)     |
   |pType          | 1 byte       | Packet type  (always use 0)           |
   |dest           | 12 bytes     | Address of destination node           |
   |src            | 12 bytes     | Address of source node                |
   ----------------|--------------|---------------------------------------|

  By the way, bigendian means that the first byte holds the most significant
value, which is the opposite of the normal way of doing things on the PC.

  For reasons better known to Novell, the checksum is always set to $ffff.
The length field contains the total length of the packet, including the IPX
header.  Transport control keeps a count of the number of routers a packet
has been through.  The format of the address is shown in Figure 2.

                       Figure 2 - The net address field
   ------------------------------------------------------------------------
   | Name          | Size (bytes) | Description                           |
   ----------------|--------------|---------------------------------------|
   |network        | 4 bytes      | Network address                       |
   |node           | 6 bytes      | Node address                          |
   |socket         | 2 byte       | Socket number                         |
   ----------------|--------------|---------------------------------------|

  Sockets are a device that lets a node decide if it will act on a packet.
It allows multiple programs on the one PC to use IPX packets completely
transparent to the others.  It also means that a broadcasted packet will only
be received by a machine if it has a socket open for that which the packet is
addressed.  So packets can be ignored by nodes that are not capable of
accepting them.  Special care must be taken to ensure that no two programs try
to send different types of packets to the same socket!

  The next order of bussiness is to tell the PC that we want to open a socket.
This is accomplished by creating an Event Control Block (ECB).  Figure 3 shows
the format of the ECB.

                      Figure 3 - Format of the ECB
   ------------------------------------------------------------------------
   | Name          | Size (bytes) | Description                           |
   ----------------|--------------|---------------------------------------|
   |Link           | 4 bytes      | Pointer to next ECB?                  |
   |ESR            | 4 bytes      | Pointer to Event Service Routine      |
   |InUse          | 1 byte       | Flag telling the ECB status           |
   |complete       | 1 byte       | Flag telling the ECB completion code  |
   |socket         | 2 bytes      | Bigendian socket number for ECB       |
   |IPXwork        | 4 bytes      | Work space for IPX                    |
   |Dwork          | 12 bytes     | Work space for driver                 |
   |immedAddr      | 12 bytes     | Address to send to.                   |
   |fragCount      | 2 bytes      | Number of fragments                   |
   |FragData       | 4 bytes      | Pointer to data fragment              |
   |FragSize       | 2 bytes      | Size of data fragment                 |
   ----------------|--------------|---------------------------------------|

  All the fields in the ECB should be set to zero before initializing the ECB.
This makes the code to initialize the ECB much nicer!  No ESR is used in my
routines which means the the program must constantly ckeck the ECB to see if
a packet has arrived.  I don't see this as any great drawback however.

  To send a broadcast, set the node address to all $ff.  This is done
automatically by my routines.

  FragData must be initialized to point to the IPX header and the data we want
to send MUST follow directly after this header.  An example of this can be
seen in Appendix B in the definition of the record type "Packet".  The ECB
need not be included in the packet record, but for simplicity I chose to do
so.

  The procedures InitSendPacket and InitReceivePacket give examples of the
initialization of both the ECB and IPX header.

  Once all of the fields are initialized, it is necessary to tell the IPX
driver about our ECB.  This is done by first opening a socket to use.
Interrupt $7A is assigned to the Novell API, and is the old way of accessing
the routines.  It is however a much easier to use than the recommended method
(in my opinion anyway).  The sub-functions that we use are given in Table 1.

                                Table 1
-----------------------------------------------------------------------------
|Function|Name        |Regs                                                 |
-----------------------------------------------------------------------------
|  $0000 |Open Socket |AL=Longevity  DX=Socket number  (bigendian)          |
|        |            |Returns:AL=Error code  DX=Socket Number  (bigendian) |
-----------------------------------------------------------------------------
|  $0001 |Close Socket|DX=Socket number  (bigendian)                        |
-----------------------------------------------------------------------------
|  $0003 |Send Packet |ES=Seg of ECB  SI=Offset of ECB                      |
-----------------------------------------------------------------------------
|  $0004 |Listen for  |ES=Seg of ECB  SI=Offset of ECB                      |
|        |packet      |Returns:AL=Error code                                |
-----------------------------------------------------------------------------
|  $0009 |Get Local   |ES=Seg of address array   SI=Offset of address array |
|        |Address     |                                                     |
-----------------------------------------------------------------------------
|  $000A |Im Idle     |None                                                 |
-----------------------------------------------------------------------------

  NOTE:  The function number is stored in BX.

  After attempting to open a socket it is advisable to test if IPX is
present.  This is done by calling int $2F with AX=$7F00.  If on return AL
does not  contain $FF, then IPX is not installed.  This is also a good point
to get your local address as your program should only have to do this once.
See the procedure InitIPX in appendix A for an example of this.

  Once we have an open socket and some set up ECBs and IPX headers, we can
tell the IPX driver about them.   First we will look at a recieving ECB and
IPX header, followed by a sending.

  For a recieve record, the IPX header does not need to be initialized at all.
However, I think it is a good idea to zero all the fields just be on the safe
side.  The ECB however, does need to have several fields set.  The inUse flag
should be set to $1D  (don't ask me why, actually it works without this, but
several of the recources I consulted did this).  The socket number must be
initialized, and remember, this is bigendian so be careful!  Finally the
fragCount, fragData and fragSize fields must be set.  All the other fields
should be set to zero!

  Once all these fields are set, call "Listen For Packet" to tell the IPX
driver about the ECB.  This will return immediatly, but if any packets arrive
for that socket they will be placed into the record.  To see if a packet has
arrived, it is necessary to check the InUse flag in the ECB.  If this is $00,
then a packet has arrived and needs to be processed before another can be
accepted.  If a packet arrives when there is an unprocessed packet, then it
will be lost.  This means that a packet should be processed as soon as
possible.  The record can be released by simply calling "Listen For Packet"
again.

  OK, we now have a recieve record waiting for a packet to arrive.  Now we
need a send record!  A send record needs all of the same fields as a receive
record, but on top of that it also needs the IPX header to be filled in.
The checksum is set to $ffff and the packet type is set to $00 (this is a
packet exchange packet).  Next the destination address is set.  For a
broadcast you should set the net address to your local net address, the node
sould be the broadcast node ($ff,$ff,$ff,$ff,$ff,$ff) and the socket should be
set up.  Your program should set up the source address with the info from the
localAddr record, and the source socket can be anything, but again, for
simplicity I usually set it to the same value as the destination socket.

  We then put some data into the data portion of the record and call "Send
Packet".  The packet will then be sent to the destination node on the network.
If the node field is set to the broadcast address, the packet will be sent to
all nodes on the network, including the source node.

  As a point of interest, you should call "Im idle" whenever your program
isn't doing anything an particular to allow the IPX driver to run more
quickly.


  So there you have it.  Hopefully you should now be able to send and receive
IPX packets on a network.  Have fun!

                                Daniel Parnell

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

    A    PPPPP  PPPPP  EEEEEE N       N DDDDDD  IIIII X     X         A
   A A   P    P P    P E      NN      N D     D   I   X     X        A A
  A   A  P    P P    P E      N N     N D     D   I   X     X       A   A
 A     A P    P P    P E      N  N    N D     D   I    X   X       A     A
 A     A P    P P    P E      N   N   N D     D   I     X X        A     A
 AAAAAAA PPPPP  PPPPP  EEEE   N    N  N D     D   I      X         AAAAAAA
 A     A P      P      E      N     N N D     D   I     X X        A     A
 A     A P      P      E      N      NN D     D   I    X   X       A     A
 A     A P      P      E      N       N D     D   I   X     X      A     A
 A     A P      P      E      N       N D     D   I   X     X      A     A
 A     A P      P      EEEEEE N       N DDDDDD  IIIII X     X      A     A

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

{ IPX 1.0 By Daniel Parnell 22 March 1994  s921878@minyos.xx.rmit.oz.au

  This unit allows the sending of IPX packets over a Novell network

  Use it if you want, but please give me some credit for it :)

  See the other file which is a chat program for info on how to use this unit

}
unit ipx;

interface

uses dos;

type
  netAddr  = array[1..4] of byte;    { The address of a network }
  nodeAddr = array[1..6] of byte;    { The address of a node in a network }

  address  = array[0..1] of word;    { A pointer to the data 0=offset 1=seg }

  netAddress = record
                 Net    : netAddr;   { network address }
                 Node   : nodeAddr;  { node address }
                 Socket : word;      { Big endian socket number}
               end;

  localAddrT = record
                 Net    : netAddr;   { my network address }
                 Node   : nodeAddr;  { my node address }
               end;

  ECBType = record
              link      : address;    { Pointer to next ECB? }
              ESR       : address;    { Event Service Routine 00000000h if none }
              inUse     : byte;       { In use flag }
              complete  : byte;       { Completeing flag }
              socket    : word;       { Big endian socket number }
              IPXwork   : array[1..4] of byte;  { IPX work space }
              Dwork     : array[1..12] of byte; { Driver work space }
              immedAddr : nodeAddr;   { Immediate local node address }
              fragCount : word;       { Fragment count }
              fragData  : address;    { Pointer to data fragment }
              fragSize  : word;       { Size of data fragment }
            end;

  IPXheader = record
                check  : word;                { big endian checksum }
                length : word;                { big endian length in bytes }
                tc     : byte;                { transport control }
                pType  : byte;                { packet type }
                dest   : netAddress;          { destination network address }
                src    : netAddress;          { source network address }
              end;

const
  MYSOCKET  : word = $869C;        { This is the DOOM official socket number }
  BROADCAST : nodeAddr = ($ff,$ff,$ff,$ff,$ff,$ff);  { Address for broadcast }

var
  localAddr    : localAddrT;

function  IPXopenSocket(longevity : byte; var socketNumber : word):byte;
procedure IPXcloseSocket(socketNumber : word);
procedure GetLocalAddress;
procedure IPXsendPacket(var E : ECBtype);
function  IPXlistenForPacket(var E : ECBtype):byte;
procedure ImIdle;
procedure InitSendPacket(var ecb : ecbType; var ipx : ipxHeader; size,sock : word);
procedure InitReceivePacket(var ecb : ecbType; var ipx : ipxHeader; size,sock : word);
procedure InitIPX;

implementation

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -