# libnodave und falsche IP



## TheEngineer0815 (4 März 2009)

Hallo

Ich arbeite gerade an einem Projekt für meine Bachelorarbeit. Dabei sollen mithilfe von Libnodave Daten aus einer SPS ausgelesen und in einem BDE weiterverarbeitet werden.

Die Verbindung läuft über TCP.

Meine Programmierkenntnisse gehen leider auch nicht weiter als das was mir auf der FH beigebracht wurde..... daher könnte es sein das ich sachen Frage die für euch bereits ganz klar sind....

Programmiert wird das ganze Mithilfe von LabWindowsCVI, also mit ANSI_C.

Die Verbindung klappt einwandfrei, allerding nur solange die richtige IP Adresse eingegeben wird. 
Bei der falschen IP bleibt das ganze Programm hängen. 
Ich nehme mal an das der Fehler bei 

fds_PLC1.rfd=openSocket(102,IP_PLC1) passiert.

ich frage Fehler aber erst bei error=daveConnectPLC(dc_PLC1) ab.

Wie kann ich einen Verbindungsfehler bei bei openSoocket abfangen?

Achja, über die Konsole erhalte ich die Fehlermeldung von OpenSocketw.c, arbeite hier allerdings bereits mit einer GUI.

Danke 
für Unterstützung und dafür nicht gleich in der Luft zerissen zu werden.

EDIT: Was gibt openSocket zurück wenn die Verbindung nicht initialisiert werden kann?


----------



## pvbrowser (5 März 2009)

Ich vermute mal, dass das Programm in der Funktion connect() 
siehe:
openSocket.c

hängt.

connect() ist eine Funktion aus der socket library des Betriebssystems.
Diese Funktion hat einen relativ großen Timeout.
Nach 1-2 Minuten sollte der connect Aufruf aber ein Timeout bekommen.
Dann sollte 0 als file desciptor zurückgeliefert werden.


----------



## TheEngineer0815 (5 März 2009)

Guten Morgen

Danke, 
hab gestern nachmittag die Source Codes durchstöbert und mir auch schon etwas in die Richtung gedacht. 
Überprüfe jetzt den Rückgabewert und fang erst mit den weiteren Schritten an wenn dieser >0 ist.

Verstehe nur eines nicht so ganz, openSocket hat int als Rückgabewert, in _daveOSserialType wird allerdings der Datentyp HANDLE gespeichert.... komme damit gedankenmäßig nicht klar..... bzw.verstehe ich nicht was hier "__declspec (dllexport) HANDLE __stdcall openSocket(const int port, const char * peer)" in openSocketw.c passiert.

ich überprüfe das ganze jetzt so:

HANDLE connectioncheck;
connectioncheck=openSocket(102,IP);
if(connectioncheck>(HANDLE)0)
{
     mach weiter...
}else
{ 
   gib "Keine Verbindung" aus
}

  Weiß nicht ob  diese Typkonvertierung (HANDLE)0 sauber ist oder besser gemacht werden könnte.


----------



## pvbrowser (5 März 2009)

openSocket.h sieht ja so aus:

+-- 19 Zeilen: Part of Libnodave, a free communication libray for Siemens S7 300/40

#ifndef __openSocket
#define __openSocket

#ifdef BCCWIN
#ifdef DOEXPORT
#define EXPORTSPEC __declspec (dllexport)
#else
#define EXPORTSPEC __declspec (dllimport)
#endif
EXPORTSPEC int openSocket(const int port, const char * peer);
#endif

#ifdef LINUX
#define EXPORTSPEC
int openSocket(const int port, const char * peer);
#endif

#ifdef CYGWIN
#define EXPORTSPEC
int openSocket(const int port, const char * peer);
#endif
#endif
+--  6 Zeilen: Changes: -----------------------------------------------------------
~
~
~
~
~
~
~
~
~
"openSocket.h" 48L, 1443C                                        1,1         Alles

Das EXPORTSPEC ist also nur unter Windows interessant und
dient nur dazu die DLL aus anderen Programmen ansprechen zu können.

Prinzipiell ist die lib aber portabel und hinter dem fd steckt nur ein einfaches int.


----------



## TheEngineer0815 (6 März 2009)

*libnodave Protokoll*

noch eine Frage zur Verbindung:

wenn ich mit "daveISOTCP" als Protokoll eingebe... welches Protokoll wird jetzt eigentlich wirklich verwendet?

S7 oder ISO over TCP

DANKE


----------



## argv_user (6 März 2009)

TheEngineer0815 schrieb:


> noch eine Frage zur Verbindung:
> 
> wenn ich mit "daveISOTCP" als Protokoll eingebe... welches Protokoll wird jetzt eigentlich wirklich verwendet?
> 
> ...



Tja, warum heißt es wohl "daveISOTCP" und nicht "daveS7"?
In Wirklichkeit ist das S7-Protokoll eine Erweiterung, besser Abwandlung,
von ISO on TCP. Läuft alles über den selben TCP-Port 112.
Du kannst Dir also aussuchen was Dir lieber ist...


----------



## pvbrowser (6 März 2009)

TheEngineer0815 schrieb:


> noch eine Frage zur Verbindung:
> welches Protokoll wird jetzt eigentlich wirklich verwendet?
> S7 oder ISO over TCP


Es gibt ein ISO on TCP
Dafür ist
#define   ISO_PORT   102
definiert.

Es handelt sich dabei um eine "Krücke" um Software, die ursprünglich ISO OSI mit TSAP's etc. verwendete auf TCP zu bringen.
Dazu wird ein eigener Header noch mal künstlich draufgesattelt.

Siehe: read_iso() und write_iso() unter
http://pvbrowser.de/pvbrowser/sf/manual/rllib/html/classrlSiemensTCP.html

Das S7 Protokoll liegt nun quasi eine Ebene höher im ISO/OSI 7 Schichtenmodell. read_iso()/write_iso() sind logisch die Transportschicht,
während das S7 Protokoll in der Anwendungsschicht oben drüber liegt.


----------



## pvbrowser (6 März 2009)

*kleiner Nachtrag*

Der ISO Port ist 102

lehrig@nb4lehrig:~> grep 102 /etc/services | grep ISO
iso-tsap        102/tcp    # ISO-TSAP Class 0
iso-tsap        102/udp    # ISO-TSAP Class 0

Der Port 112, wie oben gesagt wurde ist NICHT ISO sondern

lehrig@nb4lehrig:~> grep 112/ /etc/services
mcidas          112/tcp    # McIDAS Data Transmission Protocol
mcidas          112/udp    # McIDAS Data Transmission Protocol


----------



## argv_user (6 März 2009)

Ja is gut, 112 war ein Tippfehler...
Danke.


----------



## TheEngineer0815 (11 März 2009)

daveDisconnectPLC():

Hallo, was macht die Funktion überhaupt?
Irgendwie hab ich wenn ich mir nodave.c so ansehe den Eindruck -> die wird aufgerufen aber tut nichts.

erst passiert: 
int DECL2 daveDisconnectPLC(daveConnection * dc) {
    return dc->iface->disconnectPLC(dc);
}

dann im Interface: 

di->disconnectPLC=_daveReturnOkDummy2;

int DECL2 _daveReturnOkDummy2(daveConnection * dc){
    return 0;
}


hm.......
wie wird die Verbindung jetzt überhaupt beendet??? 
über Readbytes werden nämlich danach immer noch Daten aus der SPS ausgelesen, das möchte ich natürlich nicht.


----------



## Thomas_v2.1 (11 März 2009)

TheEngineer0815 schrieb:


> hm.......
> wie wird die Verbindung jetzt überhaupt beendet???
> über Readbytes werden nämlich danach immer noch Daten aus der SPS ausgelesen, das möchte ich natürlich nicht.



Wenn du den Socket vorher selber geöffnet hast bist du auch dafür verantwortlich diesen wieder zu schließen.

IMHO könnte sich libnodave bei einer ISO TCP-Verbindung wenigstens auf ISO-Ebene trennen (Disconnect Request).
Libnodave macht das aber nicht - scheint im Normalfall auch nicht weiter zu stören, da die SPS die Ressource spätestens beim Schließen des Sockets wieder freigibt.


----------



## TheEngineer0815 (11 März 2009)

So... jetzt stell ich mal ne blöde Frage...

was ist eigentlich unter Windows die Funktion mit der ich die Verbindung openSocket(....) die ja in der openSocket.h von libnodave zu finden ist wieder schließen kann?

Man merkt das ich außer den Vorlesungen an der FH noch nie viel mit Programmiern zu tun hatte ...


----------



## Thomas_v2.1 (11 März 2009)

TheEngineer0815 schrieb:


> was ist eigentlich unter Windows die Funktion mit der ich die Verbindung openSocket(....) die ja in der openSocket.h von libnodave zu finden ist wieder schließen kann?



Mittels 
closesocket(SOCKET s) 


http://msdn.microsoft.com/en-us/library/ms737582(VS.85).aspx

Unter Windows abschließend noch ein 
WSACleanup()


----------



## TheEngineer0815 (12 März 2009)

Morgen

closesocket(s) funktioniert leider nicht, da ich auf LAbWindowsCVI programmiere funktioniert die MSDN Library nicht.

Hab jetzt aber bei der Suche in openSocket.c die Funktion close(s) gefunden die in der Header Datei unistd.h drin ist ist....... funktioniert leider auch nicht in LabWindows....

EDIT: MSDN Library für LabWindows nachinstalliert, jetzt kanns ja richtig losgehen



Danke


----------



## Zottel (12 März 2009)

TheEngineer0815 schrieb:


> Morgen
> 
> closesocket(s) funktioniert leider nicht, da ich auf LAbWindowsCVI programmiere funktioniert die MSDN Library nicht.
> 
> ...


Es hat mir vor ein paar Tagen ein User geschrieben, daß er aus VB mit openSocket() geöffnete sockets nicht durch Aufruf von closesocket aus wins2_32.dll schließen kann.
Ich habe ihm eine geänderte Version geschickt, bei der openSocket.h um eine Funktion closeSocket() ergänzt wurde. Diese ruft lediglich closesocket() aus wins2_32.dll. 
Das anghängte Archiv enthält die geänderten Dateien.


----------



## TheEngineer0815 (12 März 2009)

Danke!

Nur noch ein Frage zum Einbinden:
Muss ich jetzt die neue openSocketw.c in mein Programm einbinden,
bzw. openSocket.h um 

int __stdcall closeSocket(SOCKET h);

ergänzen?

Und ich hoffe auch das ich den Funktionsaufruf mit closeSocker((SOCKET)fds.rfd) wohl richtig mache.


----------



## Zottel (12 März 2009)

TheEngineer0815 schrieb:


> Danke!
> 
> Nur noch ein Frage zum Einbinden:
> Muss ich jetzt die neue openSocketw.c in mein Programm einbinden,


Nein, die Funktion steht zur Verfügung, wenn du die neue libnodave.dll verwendest.
Wenn du in .NET programmierst, bräuchte es auch noch eine Ergänzung in libnodave.net.cs



TheEngineer0815 schrieb:


> bzw. openSocket.h um
> 
> int __stdcall closeSocket(SOCKET h);
> 
> ergänzen?


Ja, wenn du in C programmierst. 
Oder du schreibst  int __stdcall closeSocket(SOCKET h);
in dein Programm.
Und ich hoffe auch das ich den Funktionsaufruf mit closeSocker((SOCKET)fds.rfd) wohl richtig mache.[/quote]
Soweit ich das auswendig weiß ist es nicht falsch. Ganz richtig ist es, genau die Variable einzusetzen, die openSocket ursprünglich zurückgeliefert hat. 
Das macht dann einen Unterschied, wenn zukünftige Versionen von Libnodave hier einen selbstdefinierten Datentyp verwenden würden.


----------

