![]() |
[Studienarbeiten: Kommunikation zwischen PDAs] | ![]() |
Unter WindowsCE kann man die Infrarotschnittstelle entweder als serielle
Schnittstelle über IrCOMM ansteuern oder mit Hilfe der IrSock Erweiterung des vorhandenen
WinSock2-Standards. Im Rahmen dieser Studienarbeit wurde nur die Kommunikation über
IrSockets implementiert. Bei Benutzung von IrCOMM genügt es
aber, eine Schnittstelle des Rechners für den Betrieb als IrCOMM-Schnittstelle
zu konfigurieren und diese in der Applikation wie eine normale Schnittstelle (seriell oder
parallel) anzusteuern.
IrSock ist genaugenommen keine Erweiterung des bestehenden WinSock2 Standards für
Windows, sondern eigentlich nur die Unterstützung für TinyTP/IrLMP als weiteres Transportprotokoll , das neben TCP/IP und anderen
als Transport Service Provider über diese Sockets angesteuert werden kann. Allerdings
mußten, um auf die speziellen Eigenschaften der Infrarotkommunikation (keine festen
Adressen, kurzfristig bestehende Verbindungswege) viele Funktionen angepaßt werden. Viele
üblichen Socket-Funktionen (wie z.B. gethostbyname) werden deshalb nicht unterstützt.
Verglichen mit den normalen WinSocks gibt es außerdem noch folgende weitere
Einschränkungen bzw. Änderungen: IrSockets können nur als Stream-Sockets geöffnet
werden, nicht als Datagramm-Sockets, und IrSockets benutzen ein eigenes speziell auf die
Natur der Infrarotverbindung zugeschnittenes Addressierungsschema, das sich an den
IrDA-Standards orientiert.
IrSockets bieten eine Schnittstelle zu den IrDA-Protokollschichten TinyTP
oder IrLMP.
Um einen Server zu starten sind folgende Schritte notwendig:
Um eine Verbindung zu einem Server aufzubauen, sind folgende Schritte notwendig:
Es gibt zwei Möglichkeiten IAS-Abfragen zu benutzen. Zum einen geschieht dies implizit wenn bei den Funktionen bind oder connect ein Service-Name statt eines LSAP-Selectors angegeben wird. Zum anderen kann man auch selbst mit den Funktionen setsockopt IAS-Attribute setzten und mit getsockopt IAS-Attribute der Gegenstelle abfragen.
struct sockaddr_irda
{
u_short irdaAddressFamily;
u_char irdaDeviceID[4];
char irdaServiceName[25];
};
irdaAddressFamily | muß AF_IRDA sein. |
irdaDeviceID | Geräteadresse, die durch die Option SO_IRLMP_ENUMDEVICES der getsockopt Funktion ermittelt wurde. |
irdaServiceName | Service-Name der mit der Socket verbundenen Applikation oder ein String der Form "LSAP-SELxxx" wobei xxx eine Integerzahl zwischen 0 und 255 ist. Über die zweite Möglichkeit gibt man direkt einen LSAP-Selector ein, während die erste selbst eine wählt und diesen über IAS registriert. |
struct _DEVICELIST
{
ULONG numDevice;
IRDA_DEVICE_INFO Device[1];
}
numDevice | Nummer des Geräts in der Liste. |
Device | Hier steht die Information über das Gerät. Die Struktur wird weiter unten beschrieben. |
struct _IRDA_DEVICE_INFO
{
u_char irdaDeviceID[4];
char irdaDeviceName[22];
u_char Reserved[2];
}
irdaDeviceID | Geräteadresse, des gefundenen Geräts. |
irdaDeviceName | Name, des Gerätes. Häufig der Name des eingetragenen Benutzers. |
reserved | Reserviert für internen Gebrauch. |
struct _IAS_QUERY
{
u_char irdaDeviceID[4];
char irdaClassName[61];
char irdaAttribName[61];
u_short irdaAttribType;
union
{
int irdaAttribInt;
struct
{
int Len;
u_char OctetSeq[1];
u_char Reserved[3];
} irdaAttribOctetSeq;
struct
{
int Len;
u_char CharSet;
u_char UsrStr[1];
u_char Reserved[2];
} irdaAttribUsrStr;
} irdaAttribute;
}
irdaDeviceID | Geräteadresse, des gefundenen Geräts. |
irdaClassName | IAS-Klassenname |
irdaAttribName | IAS-Attributname |
irdaAttribType | Typ des Attributs. |
irdaAttribute | Das Attribut selbst. Da es verschiedene Typen gibt als union in C. |
Die IAS_SET Struktur ist die selbe wie IAS_QUERY mit der Ausnahme, daß das Feld
irdaDeviceID nicht vorhanden ist, da es sich beim Setzen stets um das eigene Gerät
handelt.
SOCKET accept (SOCKET s, struct sockaddr* addr, int* addrlen )
Die accept Funktion akzeptiert die erste Verbindung aus der Liste der wartenden
Verbindungen an einer Socket s. Es wird eine neue Socket erzeugt und deren Handle
zurückgegeben. Die neue Socket ist für die akzeptierte Verbindung zuständig.
Die Werte sockaddr und addrlen gelten nicht für IrSockets und sollten daher NULL sein.
int bind(SOCKET s, const struct sockaddr* addr, int namelen)
Die bind Funktion verbindet eine lokale Adresse mit einer Socket s.
Bind muß aufgerufen werden bevor Listen oder connect aufgerufen wird. Je nachdem, ob in
addr ein Service-Name oder direkt ein LSap-Selector angegeben wurde, wird der neue Service
unter IAS registriert oder direkt der gewählte Selector benutzt. Der Parameter namelen
übergibt die Größe der Struktur auf die addr zeigt.
Für IrSockets muß addr ein Zeiger auf eine Struktur vom Typ SOCKADDR_IRDA sein (hier ist ein cast nach (struct sockaddr*) nötig).
int closesocket(SOCKET s)
Die closesocket Funktion beendet eine bestehende Verbindung über die Socket s und
schließt diese. closesocket bewirkt keinen unmittelbaren Verbindungsabbruch. Gesendete
und noch nicht empfangene Pakete kann die Gegenseite empfangen, bevor die Verbindung
beendet wird.
int connect(SOCKET s, const struct sockaddr * name, int namelen)
Die connect Funktion versucht, eine Verbindung zu einem Server aufzubauen. Falls der
Service-Name im Parameter name die Form "LSAP-SELxxx" hat, wird versucht, direkt
eine Verbindung mit dem entsprechenden LSap-Selector der Gegenseite aufzubauen.
Anderenfalls wird zunächst versucht, über IAS den zum Service-Name gehörenden
LSap-Selector der Gegenseite zu finden.
Der Parameter namelen übergibt die Größe der Struktur auf die addr zeigt.
Für IrSockets muß name ein Zeiger auf eine Struktur vom Typ SOCKADDR_IRDA sein (hier ist ein cast nach (struct sockaddr*) nötig).
int getsockopt(SOCKET s,int level,int optname,chat *optval,int *optlen)
Mit der Funktion getsockopt können die für die SOCKET gesetzten Optionen abgefragt werden. Ausserdem dient diese Funktion dazu, nach Geräten zu suchen, die in Reichweite liegen und um IAS-Anfragen auszuführen. Dazu dienen folgende Optionsnamen (optname):
IRLMP_ENUMDEVICES
Mit dieser Option erhält man eine Liste, der gefundenen Geräte. Dazu übergibt man im
Parameter optval einen Zeiger auf eine Struktur vom Typ DEVICELIST.
Dies ist ein Feld von Gerätebeschreibungen, welches mit so vielen Beschreibungen gefüllt
wird, wie Platz vorhanden ist. Im optlen Parameter wird, falls die Größe nicht
ausreicht, die benötigte Größe zurückgegeben.
IRLMP_IAS_QUERY
Mit dieser Option kann man einen IAS-Eintrag der Gegenseite abfragen. Dazu wird im Parameter optval ein Zeiger auf eine Struktur vom Typ IAS_QUERY übergeben. Diese enthält beim Aufruf die Geräteadresse, die Klasse, den Attributsnamen und den Attributstyp und später die entsprechenden Rückgabewerte.
Der Parameter level sollte für diese Abfragen immer den Wert SOL_IRLMP haben.
int listen(SOCKET s, int backlog)
Die Funktion listen läßt die Socket s auf ankommende Verbindungswünsche warten. Dabei
gibt der Parameter backlog an, wie groß die Liste der auf ein accept wartenden
Verbindungen sein darf. Eine genaue Beschreibung dieses Mechanismus erfolg im Abschnitt "Wie programmiert man einen Server".
int recv(SOCKET s, char *buf, int len, int flags)
Die Funktion recv wartet auf ankommende Daten von der Gegenseite und speichert diese im
Puffer buf. Zurückgegeben wird die Anzahl der empfangenen Bytes. Der Parameter len gibt
die maximale Anzahl der zu empfangenden Zeichen an.
Recv ist eine blockierende Funktion, das heißt, die Funktion wartet solange, bis Daten
ankommen und kehrt erst dann zurück.
int send(SOCKET s, const char *buf,int len,int flags)
Die Funktion send überträgt Daten, die im Puffer buf stehen. Die Anzahl der zu
übertragenden Zeichen steht im Parameter len.
int setsockopt(SOCKET s, int level,int optname, const char *optval,int optlen)
Mit der Funktion setsockopt können Optionen für die Socket gesetzt werden. Ausserdem
können damit IAS-Informationen in der eigenen IAS-Datenbank gesetzt werden. Es stehen
unter anderem folgende Optionen (Parameter optval) zur Verfügung:
IRLMP_IAS_SET
Mit dieser Option werden Informationen in die eigene IAS-Datenbank eingetragen. Dazu
wird im Parameter optval ein Zeiger auf eine IAS_SET Struktur übergeben. Diese enthält
beim Aufruf die Geräteadresse, die Klasse, den Attributsnamen, den Attributstyp und
das Attribut selbst.
IRLMP_RAW_MODE
Mit dieser Option kann man von TinyTP auf IrLMP umschalten. Standardmäßig wird TinyTP benutzt. Diese Option muß nach dem Erzeugen der Socket mit der socket Funktion und vor jedem anderen Funktionsaufruf erfolgen.
Diese Option läßt sich in der vorliegenden Version der WindowsCE Entwicklungsumgebung
(2.0 beta) leider nicht benutzen, da die Konstante IRLMP_RAW_MODE nicht definiert ist.
IRLMP_IRLPT_MODE
Mit dieser Option kann auf den IrLPT-Modus umgeschalten werden, der speziell für die Druckausgabe auf IrDA-Druckern vorgesehen ist.
SOCKET socket(int af, int type, int protocol)
Die Funktion socket generiert eine neue Socket und gibt deren Handle zurück. Für eine
IrSocket muß af den Wert AF_IRDA, type den Wert SOCK_STREAM und protocol den Wert NULL
haben.
Bei der folgenden Auflistung von nicht unterstützten Funktionen aus der IrLMP/TinyTP-Spezifikation sollte man beachten, daß die IrSockets keine Implementierung dieser Protokolle darstellt, sondern eine Schnittstelle, mit deren Hilfe man auf diese Protokolle zugreifen kann. Da es aber keine (dokumentierte) Möglichkeit gibt, diese Implementierung der Protokolle direkt anzusprechen, ist diese Auflistung durchaus berechtigt.
Beim Testen der im Rahmen dieser Studienarbeit geschriebenen Programme gelang kein
Connect-Versuch des WindowsCE-Geräts an den Psion. Die andere Richtung funktionierte
problemlos. Woran und auf welcher Seite dieser Fehler liegt, konnte mangels weiterer
Psion-Geräte nicht festgestellt werden. Der Verbindungsaufbau zwischen zwei CE-Geräten
funktionierte problemlos.
Ebensowenig funktionierten IAS-Abfragen an den Psion, bzw. vom Psion auf dem CE-Rechner,
obwohl diese theoretisch richtig definiert und vorgesehen sind. Auch hier konnte die
Ursache für den Fehler nicht endgültig geklärt werden.
![]() |
[Studienarbeiten: Kommunikation zwischen PDAs] | ![]() |