IPX (Internetwork Packet Exchange), SPX (Sequenced Packet Exchange)

Comunicaciones. Transmisión de Datos. Socket. WinSock. Dashed. LAN (Local Area Network). Enrutado. Routable

  • Enviado por: Trax
  • Idioma: castellano
  • País: Chile Chile
  • 21 páginas
publicidad

Taller Numero 1

Comunicación de Datos

Indice.

1. Introducción 3

2. Apreciación global de IPX/SPX 3

2.1. La Familia de Direcciones AF_IPX 3

2.2. Familia de Identificadores de Protocolo de IPX 4

2.3. Transmisión a Red Local. 4

2.4. Transmisión a todas las rutas. 4

2.5. Transmisión Dirigida. 4

2.6. Algo sobre el Tamaño de Paquete de comunicación. 4

3. Cable coaxial 6

4. Códigos de los programas de Comunicación: 7

Funciones de Winsock 7

Código del programa en Visual Basic 12

Código del programa en C ++ Builder 14

Código del programa en Delphi 18

5. Conclusiones: 21

6. Bibliografía 21

1.Introducción sobre IPX/SPX

Este informe cubre una extensión a WinSock 2 eso es específico a la familia IPX de protocolos de transporte. También describe aspectos de WinSock bajo 2 funciones que requieren consideración especial o qué puede exhibir única conducta.

Este Protocolo proporciona servicios de transporte encima del IPX que conecta una red de computadoras capa: IPX para datagramas inestables, SPX para las tramas de mensajes fiables orientados a la conexión.

2. Apreciación global de IPX/SPX

Esta sección discute cómo usar el API Winsock 2 con la familia de protocolos IPX. Tradicionalmente, la especificación del Winsock 1.x se ha usado con la familia de protocolos IP como TCP y UDP. Sin embargo, con el advenimiento de Winsock 2, el API se ha actualizado para acceder una gama amplia de transportes y tipos de la red más fácilmente. El API Winsock 2 es suficientemente genérico que los programadores necesitan saber muy poco sobre las especificaciones de la implementación de IPX/SPX. Es obvio que las redes de IPX operan diferente que una red IP, y un poco de consideración de este hecho probablemente será evidente en los códigos.

2.1. La Familia de Direcciones AF_IPX

Las familias de direcciones IPX definen la estructura de direccionamiento para protocolos que usan direccionamiento por socket estándar IPX. Para estos transportes, una dirección endpoint consiste en un número de la red, dirección del nodo y número del socket.

El número de la red es un dominio administrativo y típicamente nombrados como solo ethernet o un segmento de token ring. El número del nodo es la dirección física de una estación. La combinación de red y nodo, forma una única dirección de la estación que se presume ser única en el mundo. Los números Red/nodo se representan en bloques ASCII o la anotación dashed como: “0101a040, 00001b498765” o “01-01-a0-40,00-00-1b-49-87-65”. La necesidad de cero Principal no está presente.

El número de socket IPX es un número de servicio de Res/transporte tal como un número de puerto TCP y no debe ser confundido con el descriptor de socket Winsock. Los números de Socket IPX son globales para la estación extremo y no pueden ligarse a las direcciones del Red/nodo específicas. Por ejemplo, si la estación extremo tiene dos tarjetas de red, un socket limite puede enviar y puede recibir en ambas tarjetas. En particular, los datagramas del socket recibirían los datagramas de la transmisión en ambas tarjetas.

Sockaddr_ipx tiene un largo de 14 bytes y es más corto que la estructura de referencia sockaddr de 16 bytes. Las aplicaciones de IPX/SPX pueden aceptar la longitud de 16 bytes así como la verdadera longitud. Si se usa el Sockaddr_ipx y una longitud codificada dura de 16 bytes, la aplicación puede asumir que tiene acceso a los dos bytes que siguen su estructura.

Valores de los campos.

sa_family Familia de Direcciones AF_IPX en el orden del host.

sa_netnum identificador de red IPX en el orden de la red.

sa_nodenum Dirección del nodo.

sa_socket número de socket IPX en el orden de la red.

2.2. Familia de Identificadores de Protocolo de IPX

El parámetro protocolar en socket() y WSASocket() es un identificador que establece un tipo de red y un método para identificar los varios protocolos de transporte que corren en la red. Distinto de IP, IPX no usa un solo valor protocolar para seleccionar una pila de transporte. No hay ningún requisito de la red para usar un valor específico para cada protocolo de transporte, uno es libre de asignarlos de una manera conveniente para las aplicaciones de Winsock. Se evitan valores entre 0 ..255 para evitar colisiones con los valores protocolares PF_INET correspondientes.

Nombre Valor Tipo Socket Descripción

Reservado

0-255

Reservados para los valores protocolares de PF_INET.

NSPROTO_IPX

1000 - 1255

SOCK_DGRAM

SOCK_RAW

Datagrama para IPX.

NSPROTO_SPX

1256

SOCK_STREAM

SOCK_SEQPKT

Intercambio del paquete fiable que usa paquetes fijo-clasificados según tamaño.

Nótese que cuando NSPROTO_SPX se especifica, el protocolo SPX II se utilizará automáticamente si ambos endpoints son capaces de hacerlo.

2.3. Transmisión a Red Local.

Una transmisión puede hacerse a la red localmente atada poniendo sa_netnum a binario 0 y sa_nodenum a binario 1. Esta transmisión puede enviarse a la red primaria para el dispositivo, o todos ataron redes localmente a la opción del proveedor de servicio. Las transmisiones a la red local no son propagadas por routers.

2.4. Transmisión a todas las rutas.

Una transmisión general a través del internet es lograda poniendo los sa_netnum y campos del sa_nodenum a binario 1. El proveedor de servicio traduce esta demanda a un “paquete del tipo 20” que las routers de IPX reconocen y remiten. Su paquete visitará todas las subredes y puede duplicarse varias veces. Los receptores deben manejar muchas copias duplicadas de su datagrama.

El uso de este tipo de la transmisión es muy impopular entre administradores de la red y su uso debe estar sumamente limitado. Muchos routers desactivan este tipo de transmisión y dejan invisible su paquete a partes de la subred.

2.5. Transmisión Dirigida.

Generalmente considerado más red-amistoso que la transmisión a todas las rutas, una transmisión dirigida limita la transmisión a la red local que usted especifica. Llene sa_netnum del número de la red designado y sa_nodenum con binario 1. Las Routers remiten esta demanda a la red del destino donde se vuelve una transmisión local. Las redes del intermedio no ven este paquete como una transmisión.

2.6. Algo sobre el Tamaño de Paquete de comunicación.

El tamaño de paquete de medios de comunicación afecta la habilidad de protocolos de IPX de transferir datos por las redes y puede nos puede desafiar a tratar con una manera de transporte independiente. IPX no segmenta paquetes, ni informa cuando se dejan caer paquetes por violaciones del tamaño. Esto significa que alguna entidad en una estación del extremo debe mantener el conocimiento del tamaño máximo de paquete a ser usado en cualquier camino de la interred. Tradicionalmente, el datagrama de IPX y los servicios orientados a la conexión SPX, han dejado esta carga a la aplicación, mientras SPXII ha usado negociación de Paquete Internet Grande para manejarlo transparentemente.

Winsock intenta poner límites racionales de tamaño de paquete para sus varios protocolos de IPX como se vera a continuación. Estos límites pueden verse y pueden ser modificados por aplicaciones vía las opciones de socket de get/set. Al determinar tamaño máximo de paquete, las tres áreas de preocupación son:

  • El tamaño de paquete de medios de comunicación

  • El tamaño paquete Routable

  • El tamaño de paquete de extremo-estación

El tamaño de paquete de medios de comunicación refleja el tamaño de paquete máximo aceptable en cualquier medio de comunicación. El tamaño del paquete varía entre medios de comunicación como ethernet y token ring. La cantidad de espacio de los datos dentro de un paquete también puede variar dentro de un medios de comunicación dados y puede depender del arreglo de título de paquete. Por ejemplo, los datos eficaces clasifican según tamaño de un paquete del ethernet varía y depende adelante si es de tipo Ethernet II, Ethernet 802.2 o Ethernet SNAP.

El tamaño paquete Routable refleja el tamaño máximo de paquete que una router puede remitir. Se construyen routers de IPX modernas para dirigir cualquier tamaño del datagrama que con tal de que permanezca dentro de la red. Sin embargo, las routers más viejas pueden limitar tamaño máximo de paquete a 576 bytes, incluyendo los títulos protocolares.

El tamaño de paquete de extremo-estación refleja el tamaño de los buffer del los extremo-estación que están en espera y han anunciado para recibir paquetes entrantes. Incluso cuando los medios de comunicación y límites de la router permiten un paquete a través de, puede ser desechado por el extremo-estación si la aplicación receptor ha anunciado un buffer más pequeño. Muchas aplicaciones de IPX/SPX tradicionales limitan tamaño del buffer de recepción tal que la porción de los datos no debe ser más grande que 512 o 1024 bytes.

3. Cable coaxial

Con respecto a las conexiones de red del tipo coaxial, la especificación IEEE 802.3 es clara:

"La MAU debe proporcionar aislamiento entre los circuitos de la capa física del DTE y el cable troncal coaxial. La impedancia de aislamiento medida entre cada conductor en los circuitos de la capa física del DTE y tanto el conductor central como el blindaje del cable coaxial debe ser mayor que 250k ohmios a 50, 60 Hz. Además la impedancia de aislamiento entre la tierra del DTE y el blindaje del cable coaxial debe ser menos de 15 ohmios entre 3 Mhz y 30 Mhz. Los medios de aislamiento deben soportar 500 Vac rms durante un minuto."

Estándar IEEE 802.3

Al contrario de otras conexiones con el equipo de usuario, tales como módems o video, la conexión Ethernet está totalmente aislada del equipo del usuario. La primera indicación de este hecho es que el espigo del conector hembra montado en el chasis está aislado del mismo por medio de un anillo plástico. En una tarjeta adaptadora para Ethernet, se dedica una sección especial aislada rodeada de áreas de espaciamiento para la interfaz coaxial. Unos aisladores especiales de alto voltaje en la tarjeta sirven de puente sobre el área de espaciamiento y permiten la comunicación entre la estación del usuario y la interfaz coaxial. Este sistema brinda excelente inmunidad ante daños relacionados con sobretensiones, excepto cuando estas sean muy grandes. Con el fin de limitar la magnitud del voltaje que puede existir entre el cable Ethernet y la estación del usuario, los adaptadores Ethernet están equipados con un supresor de sobretensiones de alto voltaje del tipo "spark gap". Para sobretensiones de más de 2000 voltios, este supresor se activará y derivará el pico hacia el chasis de la estación del usuario con el fin de evitar la ruptura del adaptador Ethernet. Desafortunadamente el pico de energía inyectado en el chasis por este supresor de sobretensiones puede hacer que otros puertos en la estación de trabajo se dañen, particularmente los puertos RS-232 que están conectados a otros equipos aterrizados tales como impresoras o plotters (los puertos conectados a equipo no aterrizado, tales como un ratón, no se dañarán). La conexión Thin Ethernet por estándar debe tener una conexión de baja impedancia a través de la barrera de aislamiento, para las altas frecuencias (ver la nota posterior). Esto se logra usando un filtro con condensador. La consecuencia desafortunada de tener este condensador es que el ruido de alta frecuencia se acopla entre el chasis del nodo de red y el cableado Ethernet. Esto permite que el ruido de tierra inter-sistema penetre a la red, lo cual puede interrumpir las comunicaciones de datos.

El estándar IEEE 802.3 especifica que cualquier segmento coaxial Ethernet que esté interconectado, debe ser aterrizado sólidamente (a tierra física) y en un solo lugar. Esta importante condición ayuda a reducir el ruido de tierra inter-sistema, aunque es llevada a la práctica muy raramente. Los administradores de la red deberían conocer la localización del punto de tierra del Ethernet y verificar que es el único punto de tierra desconectándolo periódicamente y probando la ausencia de continuidad a tierra por medio de un probador de continuidad.

4. Códigos de los programas de Comunicación:

Los programas a continuación descritos utilizan Winsock propio de cada uno de los lenguajes, y ocupando una librería de manejo del protocolo IPX.

Para la comunicación se utilizaron llamados a la API de Windows, específicamente a Winsock, la cual permite comunicar maquinas.

Se utilizaron las siguientes funciones de winsock:

WSAStartup:

La función WSAStartup inicia el uso del DLL Windows Sockets para un proceso.

int WSAStartup (

WORD wVersionRequested,

LPWSADATA lpWSAData

);

Parámetros

wVersionRequested [in] La mas reciente versión de Windows Sockets que el programa puede usar. El byte alto indica la revisión, el byte bajo indica la versión.

lpWSAData [out] Un puntero a la estructura de datos WSADATA que va a recibir los detalles de la implementación de Windows Sockets.

Socket:

La función Socket crea un socket que esta enlazado a un respectivo proveedor de servicios.

SOCKET socket (

int af,

int type,

int protocol

);

Parámetros

af [in] Una especificación de familia de direcciones.

type [in] Un tipo de especificación para el nuevo socket.

protocol [in] Un protocolo en particular para ser usado que es especifico a la familia de direcciones.

Setsockopt

La función setsockopt configura el socket.

int setsockopt (

SOCKET s,

int level,

int optname,

const char FAR * optval,

int optlen

);

Parámetros

s [in] Un descriptor que identifica al socket.

level [in] El nivel en el cual la opción es definida los niveles soportados son SOL_SOCKET y IPPROTO_TCP.

optname [in] La opción del socket la cual va a ser seteada.

optval [in] Un puntero al buffer en el cual esta el valor de la opción que se va a setear.

optlen [in] El tamaño del buffer optval.

Bind

La función Bind asocia una dirección local con un socket.

int bind (

SOCKET s,

const struct sockaddr FAR* name,

int namelen

);

Parámetros

s [in] Un descriptor identificando al socket no asociado.

name [in] La dirección para asignar el socket. La estructura sockaddr se define por los siguientes campos: sa_netnum, sa_nodenum, siipx.sa_socket, sa_family

namelen [in] El largo de name.

ioctlsocket

Esta función controla el modo del socket.

int ioctlsocket (

SOCKET s,

long cmd,

u_long FAR* argp

);

Parámetros

s [in] Un descriptor que identifica a un socket.

cmd [in] El comando a realizar en el socket s.

argp [in/out] Un puntero a un parámetro para cmd.

shutdown

Esta función desabilita enviar y/o recibir en un socket.

int shutdown (

SOCKET s,

int how

);

Parámetros

s[in] Un descriptor que identifica a un socket.

how[in] Una bandera que indica que operación va a ser desactivada.

Closesocket

Esta función cierra un socket.

int closesocket (

SOCKET s

);

Parámetros

s[in] Un descriptor que identifica a un socket.

WSACleanup

Termina el uso del windows socket DLL.

int WSACleanup (void);

sendto

Esta función envía datos a una destinación especifica.

int sendto (

SOCKET s,

const char FAR * buf,

int len,

int flags,

const struct sockaddr FAR * to,

int tolen

);

Parámetros

s[in] Un descriptor que identifica a un socket.

buf[in] Un buffer que contiene los datos a ser trasmitidos.

len[in] El largo de los datos en buf.

flags[in] Especifica el modo en que la llamada es hecha.

to[in] Un puntero opcional a la dirección del socket objetivo.

tolen[in] El tamaño de la dirección en to.

Recvfrom

Esta función recibe un datagrama y guarda la dirección que lo envio.

int recvfrom (

SOCKET s,

char FAR* buf,

int len,

int flags,

struct sockaddr FAR* from,

int FAR* fromlen

);

Parámetros

s[in] Un descriptor que identifica a un socket.

buf[out] Un buffer que contiene los datos a ser recibidos.

len[in] El largo de los datos en buf.

flags[in] Especifica el modo en que la llamada es hecha.

from[out] Un puntero opcional a una dirección con la dirección que envía.

fromlen[in/out] El tamaño de la dirección en from.

Código del programa en Visual Basic 6.0

Option Explicit

Private Sub Form_Load()

Dim RetVal As Integer

RetVal = vbIPXInitialize(Socket) 'Inicializa IPX

If RetVal = 0 Then 'Chequea si la inicialización fue exitosa. 0 = No, 1 = Si

MsgBox "IPX: Fallo la Iniciación"

End

End If

Text1.SelText = "IPX init: Exitoso" & vbCrLf

Text1.SelText = "Socket: Open Port: " & Socket & vbCrLf

Text1.SelText = "Socket: Esperando" & vbCrLf

Text1.SelText = "MaxPacketSize: " & vbIPXGetMaxPacketSize & vbCrLf & vbCrLf

Text2.MaxLength = 128 'Largo máximo del Mensaje.

End Sub

Private Sub Form_Unload(Cancel As Integer)

vbIPXShutdown

End Sub

Private Sub Text2_KeyPress(KeyAscii As Integer)

If (KeyAscii = 13) Then 'Si se Presiona enter

KeyAscii = 0

If Text2.Text = "" Then Exit Sub 'No enviar un string vacío

BroadCast (Text2.Text) 'Convertir el texto y enviarlo a todos

Text1.SelText = "LOCAL:" + Text2.Text + vbCrLf

Text2.Text = "" 'Limpiar la typebox

End If

End Sub

Private Sub Timer1_Timer()

Dim RetVal As Integer, Packet As PacketType

Dim i As Long

Dim Node As String, PacketStr As String

RetVal = vbIPXCheckForPacket(Packet) 'Existe un paquete esperando

If RetVal = 1 Then ' 1 = Si

PacketStr = GetMsg(Packet) 'Recibir el Mensaje

For i = 1 To 6

Text1.SelText = Format(Hex(Packet.Node(i)), "00") + ":"

Next i

Text1.SelText = PacketStr & vbCrLf

End If

End Sub

Modulos:

IPX2.bas

Public Const Socket As Long = &HFF

Public Sub BroadCast(Message As String)

Dim Packet As PacketType

Dim i As Long

Packet.data(0) = Len(Message) 'Se debe enviar el largo del mensaje

For i = 1 To Packet.data(0)

Packet.data(i) = Asc(Mid(Message, i, 1)) 'Convierte Chars a Ints

Next i

vbIPXBroadcastPacket Packet 'Enviar el paquete

End Sub

Public Function GetMsg(Packet As PacketType) As String

Dim PacketStr As String

For i = 1 To Packet.data(0) 'Leer todos los chars

PacketStr = PacketStr & Chr(Packet.data(i)) 'Convertir y concatenar.

Next i

GetMsg = PacketStr 'Retornar el mensaje

End Function

VBNet.bas

Type PacketType

Node(1 To 6) As Byte

data(300) As Byte

End Type

Declare Function vbIPXInitialize Lib "vbnet32" (ByVal Socket As Integer) As Integer

Declare Function vbIPXGetMaxPacketSize Lib "vbnet32" () As Integer

Declare Function vbIPXCheckForPacket Lib "vbnet32" (paket As PacketType) As Integer

Declare Sub vbIPXStartListening Lib "vbnet32" ()

Declare Sub vbIPXStopListening Lib "vbnet32" ()

Declare Sub vbIPXShutdown Lib "vbnet32" ()

Declare Sub vbIPXBroadcastPacket Lib "vbnet32" (paket As PacketType)

Declare Sub vbIPXSendPacket Lib "vbnet32" (paket As PacketType)

Código del programa en C ++ Builder 4

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "Unit1.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

#include <Windows.h>

#include <winsock.h>

#include <wsipx.h>

#include <stdio.h>

// tamaño maximo de un paquete

#define MAILPACKETSIZE 300

// El ipx no esta inicializado

int initialized=0;

// struct IPXPacket - Esta es la estructura del paquete que vamos a enviar.

struct IPXPacket {

BYTE node[6];

BYTE data[MAILPACKETSIZE+1];

};

SOCKET sockhandle;

SOCKET Sock=0xff;

WSADATA wsadat;

unsigned oursocknum=0x8849;

SOCKADDR_IPX siipx;

TForm1 *Form1;

// showerrorbox - muestra un mensaje con el error y luego sale del proceso

void showerrorbox(char*mmm) {

MessageBox(NULL,mmm,NULL,MB_TASKMODAL | MB_OK);

ExitProcess(1);

}

// inicializa el ipx

short IPXInitialize(UINT socc) {

if (initialized) return 0; //si ya esta inicializado sale

if (WSAStartup(0x101,&wsadat)) showerrorbox("Error en inicio del Socket Windows"); //inicializa el uso del DLL para el programa

sockhandle=socket(AF_IPX,SOCK_DGRAM,NSPROTO_IPX); //crea un socket IPX para el programa

if (sockhandle==INVALID_SOCKET) showerrorbox("Error en initSocket"); //

oursocknum=socc; //

int dobroad=1; //broadcast activado

if (setsockopt(sockhandle,SOL_SOCKET,SO_BROADCAST,(char FAR*)&dobroad,sizeof(int))) //activa el broadcast

showerrorbox("Error en SetSockOpt");

//Limpia las direcciones para realizar el bind

memset(siipx.sa_netnum,0,4); //netnum=0.0.0.0

memset(siipx.sa_nodenum,0,6); //nodenum=00.00.00.00.00.00

siipx.sa_socket=oursocknum; //socket=socc

siipx.sa_family=AF_IPX; //familia=AF_IPX

WSASetLastError(0);

//Enlaza el socket de windows a nuestro socket ipx

if (bind(sockhandle,(LPSOCKADDR)&siipx,sizeof(SOCKADDR))) { //enlaza sockhandle a la direccion de siipx

closesocket(sockhandle); //cierra el socket si hay un error

WSACleanup(); //limpia Windows socket

showerrorbox("Error en bindSocket"); }

u_long nonblockingmode=1; //nonblocking activado

//Inicializa el socket para I/O

if (ioctlsocket(sockhandle,FIONBIO,&nonblockingmode)) //setea el nonblocking en nuestro socket

showerrorbox("Error en ioctlsocket");

initialized=1;

return 1;

}

// vbIPXShutdown - cierra el socket y termina el socket de windows

void IPXShutdown() {

if (initialized==0) return;

if (shutdown(sockhandle,2)) showerrorbox("Error en socket Shutdown"); //desactiva el envio en el socket

if (closesocket(sockhandle)) showerrorbox("Error en closesocket"); //cierra el socket

WSACleanup(); //termina el uso del

DLL Windows socket

initialized=0;

}

// BroadcastPacket - manda un paquete a todo computador en el mismo segmento de red

void IPXBroadcastPacket(IPXPacket*ipxpak) {

siipx.sa_family=AF_IPX; //familia=AF_IPX

memset(siipx.sa_netnum,0x0,4); //netnum=0.0.0.0

memset(siipx.sa_nodenum,0xff,6); //nodenum=FF.FF.FF.FF.FF.FF(broadcast)

siipx.sa_socket=oursocknum; //socket=oursocknum

if (sendto(sockhandle,(char FAR*)&ipxpak->data[0],MAILPACKETSIZE-1,0,(sockaddr FAR*)&siipx,14)==SOCKET_ERROR) //envia el paquete

showerrorbox("Error en Broadcast");

}

// CheckForPacket - revisa si existe un paquete y si existe lo copia dentro de el registro

short IPXCheckForPacket(IPXPacket*ipxpak) {

int sizz=14; //tamaño del

paquete = 14

memset(siipx.sa_nodenum,0xff,6); //nodenum=FF.FF.FF.FF.FF.FF(broadcast)

siipx.sa_family=AF_IPX; //familia=AF_IPX

siipx.sa_socket=oursocknum; //socket=oursocknum

if (recvfrom(sockhandle,(char FAR*)&ipxpak->data[0],MAILPACKETSIZE,0,(LPSOCKADDR)&siipx,&sizz)==SOCKET_ERROR) { //recive el paquete si

existe

if (WSAGetLastError()!=WSAEWOULDBLOCK) { char buu[30];

sprintf(buu,"recv error: %d",WSAGetLastError()); showerrorbox(buu); }

return 0; }

memcpy(ipxpak->node,siipx.sa_nodenum,6); //copia la dirección

de donde se recibio

return 1;

}

//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormActivate(TObject *Sender)

{ Memo1->Clear();

Memo1->Lines->Add("IPX init: Success");

Memo1->Lines->Add("Socket: Open Port: 255");

Memo1->Lines->Add("Socket: Listening");

Memo1->Lines->Add("MaxPacketSize: 300");

IPXInitialize(Sock);}

//---------------------------------------------------------------------------

void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)

{ IPXPacket pak;

int largo,i;

if(Key==13)

{ Key=0;

largo=Edit1->Text.Length();

pak.data[0]=largo;

for (i=1;i<=largo;i++)pak.data[i]=Edit1->Text[i];

IPXBroadcastPacket(&pak);

Edit1->Text="";

};

}

//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{ IPXPacket pak;

int i;

AnsiString node;

AnsiString msg;

if (IPXCheckForPacket(&pak))

{

Memo1->Text=Memo1->Text+"\r\n";

for (i=0;i<6;i++)

node=node+IntToHex(int(pak.node[i]),2)+":";

for (i=1;i<=pak.data[0];i++)

msg=msg+char(pak.data[i]);

Memo1->Lines->Add(node+msg);

}

}

Código del programa en Delphi 5

unit Unit1;

interface

uses

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

winsock, StdCtrls, IPXUnit, ExtCtrls;

const

// tamaño maximo de un paquete

Mailpacketsize=300;

// IPXPacket - Esta es la estructura del paquete que vamos a enviar.

type

ipxpacket=record

node : array[0..6] of byte;

data : array[0..300] of byte;

end ;

TSockAddrIPX = record

sa_family : short;

sa_netnum : array [0..3] of Byte;

sa_nodenum : array [0..5] of Byte;

sa_socket : u_short;

end;

TForm1 = class(TForm)

Edit1: TEdit;

Memo1: TMemo;

Timer1: TTimer;

GroupBox1: TGroupBox;

procedure FormActivate(Sender: TObject);

procedure Timer1Timer(Sender: TObject);

procedure Edit1KeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

private

{ Private declarations }

public

{ Public declarations }

initialized:boolean;

sockhandle:tsocket;

sock:tsocket;

oursocknum:tsocket;

wsadat :TWSAdata;

siipx:TsockAddrIPX;

end;

var

Form1: TForm1;

initialized:boolean;

sockhandle:tsocket;

sock:tsocket;

oursocknum:tsocket;

wsadat :TWSAdata;

siipx:PsockAddrIPX;

ipxpak:ipxpacket;

implementation

{$R *.DFM}

// showerrorbox - muestra un mensaje con el error y luego sale del proceso

procedure showerrorbox(s:string);

begin

Application.MessageBox(pchar(s),('Error'),MB_OK);

ExitProcess(1);

end;

procedure TForm1.FormActivate(Sender: TObject);

var

i:integer;

nonblockingmode:u_long;

begin

Memo1.clear;

Memo1.lines.add('IPX init: Exitoso');

Memo1.lines.add('Socket: Open Port: 255');

Memo1.lines.add('Socket: Listening');

Memo1.lines.add('MaxPacketSize: 300');

Memo1.lines.add('');

Edit1.text:='';

// inicializa el ipx

Sock:=$ff;

oursocknum:=$8849;

if (WSAStartup($101,wsadat)=SOCKET_ERROR) then

showerrorbox('Windows Sockets startup failed');

sockhandle:=socket(AF_IPX,SOCK_DGRAM,NSPROTO_IPX);

if (sockhandle=INVALID_SOCKET) then showerrorbox('initSocket failed');

oursocknum:=sock;

i:=1;

if (setsockopt(sockhandle,SOL_SOCKET,SO_BROADCAST,@i,sizeof(integer))=SOCKET_ERROR) then

showerrorbox('SetSockOpt failed');

for i := 0 to 3 do

siipx.sa_netnum[i] := $0;

for i := 0 to 5 do

siipx.sa_nodenum[i] := $0;

siipx.sa_socket:=oursocknum;

siipx.sa_family:=AF_IPX;

WSASetLastError(0);

// bind the Windows socket to our IPX socket

if (bind(sockhandle,PSockAddr(@siipx)^,sizeof(TSockAddrIPX))=SOCKET_ERROR) then

begin

closesocket(sockhandle);

WSACleanup();

showerrorbox('bindSocket failed');

end;

nonblockingmode:=1;

// Initialize socket for I/O

if (ioctlsocket(sockhandle,FIONBIO, nonblockingmode)=SOCKET_ERROR)then

showerrorbox('ioctlsocket failed');

end;

procedure TForm1.Timer1Timer(Sender: TObject);

var

sizz,i:integer;

msg,node:string;

begin

sizz:=14;

if (recvfrom(sockhandle,ipxpak.data[0],MAILPACKETSIZE,0,PSockAddr(@siipx)^,sizz)=SOCKET_ERROR) then

begin

if (WSAGetLastError()<>WSAEWOULDBLOCK) then

Application.MessageBox(pchar('Recive Error'),('Error'),MB_OK);

end

else

begin

node:='';

msg:='';

for i := 0 to 5 do

begin

ipxpak.node[i]:=siipx.sa_nodenum[i];

node:=node+inttohex(siipx.sa_nodenum[i],2)+':';

end;

for i:=1 to ipxpak.data[0] do

msg:=msg+chr(ipxpak.data[i]);

memo1.lines.add(node+msg);

end

end;

procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

var

pak:ipxpacket;

i:integer;

begin

if Key=13 then

begin

pak.data[0]:=length(edit1.text);

for i:=1 to length(edit1.text) do

pak.data[i]:=ord(edit1.text[i]);

for i := 0 to 3 do

siipx.sa_netnum[i] := $ff;

for i := 0 to 5 do

siipx.sa_nodenum[i] := $ff;

if (sendto(sockhandle,pak.data[0],MAILPACKETSIZE-1,0,PSockAddr(@siipx)^,14)=SOCKET_ERROR) then

showerrorbox('Sendto (Broadcast) Failed');

edit1.text:='';

end;

end;

end.

5. Conclusiones:

Luego de elaborar este trabajo y desarrollar los programas en los distintos lenguajes nos dimos cuenta de la importancia de los protocolos de comunicación para establecer una red.

Lo más difícil fue encontrar librerías que nos permitieran trabajar en los distintos lenguajes, después de buscar encontramos una Liberia VBNET hecha en C++, que le daba las funciones de IPX a programas en Visual Basic, a partir de esta librería, que estaba bajo una licencia GNU, se pudo entender como se trabaja con los Sockets de Windows y pudimos extender la aplicación a distintos lenguajes como C++ y Delphi, utilizando la poderosa librería Winsock que es la que gobierna todas las comunicaciones de Windows, no pudimos entrar mas a fondo ya que como esta librería es un DLL de Microsoft, no se permite ni siquiera ver el código fuente de esta.

La investigación y la información sobre IPX es muy poca, por ser este un protocolo casi obsoleto y solo utilizado en redes Novell, la implementación de este protocolo en los distintos lenguajes fue mas o menos complicada, ya que el winsock esta hecho mas para TCP y no existen objetos IPX, por lo que tuvimos que entrar mas a fondo para poder realizar la comunicación.

La implementación en Visual Basic se realizo utilizando la librería VBNET32 que incorporaba objetos con soporte IPX, esta fue la más fácil ya que no se necesito ingresar en las llamadas a winsock.

En C++, tuvimos que adaptar dicha librería para que funcionara, esto lo hicimos mirando los fuentes y viendo como funcionaban los adaptamos a nuestro programa.

En Delphi tuvimos que a traducir el código C++, lo cual no fue muy fácil debido a que C++ es un lenguaje mucho más potente y con un manejo de memoria mucho mas claro que Delphi.

Lo más agradable para nosotros fue que todas las versiones del programa podían comunicarse entre sí, ya que teníamos la misma estructura de paquete y los mismos puertos, esto fue muy satisfactorio.

Existe un problema al realizar el programa en GCC, ya que para que Linux acepte el protocolo IPX es necesario recompilar el Kernel, tarea que no logramos concretar, a pesar de estar bien documentada, pero incluso en los HOWTO de Linux decía que esta era una tarea mas o menos complicada.

La implementación en Java no se pudo realizar debido a que los sockets de Java no soportan IPX, solo TCP, para llevar a cabo esto se deberían crear librerías desde cero lo cual no pudimos hacer debido a que no tenemos un amplio conocimiento de dicho lenguaje y la maquina virtual de Java.

6. Bibliografía

Ayuda de C++, Delphi

Microsoft Developer Network

Internet:

http://developer.novell.com/support/winsock/doc/wsanx-1.htm

http://altavista.com/

http://www.google.com/

http://www.yahoo.com

http://members.xoom.com/dosuser/vbipx.htm

http://www.apress.ru/pages/bokovikov/delphi/indexe.html