Netzwerk-Funktionen laufen 'ewig' auf Eckelmann-SPS

Begonnen von MKr, 27. Oktober 2011, 16:32:48

Vorheriges Thema - Nächstes Thema

0 Mitglieder und 1 Gast betrachten dieses Thema.

peewit

#15
hallo

ich hoffe du hast ein wenig geduld und wille, damit wir das gemeinsam lösen

meiner meinung nach passiert beim IP_CONTROL etwas mit dem ich nicht gerechnet habe (tja, ist meistens so)
ich glaube das der ip_control im prinzip zyklisch versucht die verbindung aufzubauen, aber immer scheitert weil
etwas nicht geplantes passiert.

damit du dies genauer bestimmen kannst, musst du am besten die network.lib zu einem normalen projekt machen
und damit deinen test machen , damit du den ip_control auch debuggen kannst.

am besten du nimmst gleich die zukünftige network.lib v1.20 (siehe anhang)

in zeile 74 beim ip_control solltest du einen breakpoint setzen

73 UDP_INIT: (* UDP_CLIENT + SERVER *)
74  socket := SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_UDP);
75 IF socket < 0 THEN
76 c_status := 1; (* SysSockCreate failed *)
77 state := C_CLOSE;
78 ELSE
79 SysSockSetOption(socket, SOCKET_SOL, SOCKET_SO_BROADCAST, ADR(dint_true), SIZEOF(dint_true)); (* allow broadcast *)
80 SysSockIoctl(socket, SOCKET_FIONBIO, ADR(dint_true)); (* put socket in non-blocking mode *)
81 sockaddr.sin_family := SOCKET_AF_INET;
82 sockaddr.sin_port := SysSockHtons(c_port);
83 sockaddr.sin_addr := SEL(c_mode = 1, SOCKET_INADDR_ANY, SysSockNtohl(c_ip));
84
85 IF c_mode >= 2 THEN (* SERVER Mode *)
86 IF SysSockBind(socket, ADR(sockaddr), SIZEOF(sockaddr)) THEN
87 c_ready := TRUE; (* Connected *)
88 state:= C_WAIT;
89 ELSE
90 c_status := 2; (* SysSockBind failed *)
91 state := C_CLOSE;
92 END_IF;
93 ELSE
94 c_ready := TRUE; (* Connected *)
95 state:= C_WAIT;
96 END_IF;
97 END_IF;

(* ---------------------------------------------- *)

der normaler ablauf wären folgende zeilen

74
79-83
94-95

mich würde interessen welchen verlauf das programm an dieser stelle nimmt , und du mir das dann möglichst gut beschreibst

weiters wäre es dann auch interessant was dann im Abschnitt C_CLOSE (zeile 196-209) passiert
(weiteren breakpoint setzen)

irgendwas löst ein beenden der verbindung aus, ohne eine fehlercode zu setzen


ist dein sntp-server im selben netzwerk ?
wenn nicht , hast du eine korrekte gateway adresse eingestellt ?



[gelöscht durch Administrator]

EMV-Fuzzi

Hallo peewit!

Ich beobachte hier ein interessantes Phaenomen!

Fakt ist, dass kein Socket angelegt werden kann:
Der Returnwert von SysSockCreate(...) steht auf "-1" = "16#FFFFFFFF"
(vgl. Screenshot im Anhang)

und jetzt das Kuriose:
Wenn ich vor Aktivieren des Programms mit xTrigger in Zeile 74 einen
Breakpoint setze und mich dann per F10 (Einzelschritt ueber) durch
das Programm hangele, kommt irgendwann der Timeout
(SNTP.Error = 16#FF000000)

Hier die Liste der Zeilen, auf denen ich wieder F10 druecke:
74, 75, 76, 77, 78, 97, 213, 228, 246, 250, 256, 308, 309, 365,
395, 396, 397, 398, 399, 401, 402, 403, 406, 410, 413, 416, 420, 455,
IP_CONTROL wird verlassen -> F5 (Start) -> TimeOut-Fehlercode

Wenn ich beim Breakpoint auf Zeile 74 F5 (Start) druecke, dann habe ich
eine Endlosschleife aus der er sich nicht befreien kann.

Wenn ich jetzt den Breakpoint auf Zeile 73 aendere, bemerke ich, dass der
"state" nach jedem Druck auf F5 den Wert von 16#1F auf 16#FB wechselt.

Der Ablauf hier ist aehnlich, wie vorher:
73, 74, 75, 76, 77, 78, 97, 213, 228, 246, 250, 256, 308, 309, 365,
395, 396, 397, 398, 399, 401, 402, 403, 406, 410, 413, 416, 420, 455,
IP_CONTROL wird verlassen -> F5 (Start) -> Breakpoint (state = 16#FB)
73, 101, 120, 145, 168, 189, 196, 197, 198, 203, 208, 213 (state = 0), 228, 246,
250, 256, 308, 309, 365, 395, 406, 410, 411, 413, 416, 420, 455,
IP_CONTROL wird verlassen -> F5 (Start) -> Breakpoint (state = 16#1F)



Da es sich hier scheinbar um ein Timing-Problem beim Erstellen des Sockets
handelt, habe ich testweise mal einen weiteren Schritt in die CASE-Anweisung
eingebaut:

CASE state OF

UDP_INIT: (* UDP_CLIENT + SERVER *)
socket := SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_UDP);
state := UDP_INIT_2;
UDP_INIT_2:
IF socket < 0 THEN
c_status := 1; (* SysSockCreate failed *)
state := C_CLOSE;
ELSE


Mit dieser Aenderung kommt bei Ausfuehrung sofort der Fehlercode
16#01000000 (SysSockCreate nicht erfolgreich ausgefuehrt) und ich
kann wiederholt das Programm mit xTrigger aktivieren.

Es scheitert also bereits beim Erstellen des Socket und somit ist es
auch irrelevant, daß sich alle Geraete im Netzwerk im selben Subnetz
befinden.


[gelöscht durch Administrator]

peewit

hallo

ich muss mir das erst alles in ruhe ansehen, um das eigentliche problem zu finden
warum es zu keiner stabilen fehlermeldung kommt, bzw. diese nicht bleibt

aber das eigentliche problem ist trotzdem das man keinen socket einrichten kann
du könntest mal probweise im sntp_client eine andere port nummer probieren (z.b. 15000)


peewit

hallo

denke das grundproblem gefunden zu haben , was die instabile fehlermeldung betrifft

1. beim socket initialisieren wird auch ein IP_C.TIME_RESET = TRUE ausgelöst
der alle fehlermeldungen rücksetzen soll

2. mitten im baustein wird im ersten zyklus sofort ein fehler erkannt
    und fehler 0x 01000000 ausgegeben, was richtig ist

3. weitere schritt ist das schliessen aller socket

4. zum ende des bausteins kommt der IP_C.TIME_RESET = TRUE zu tragen und löscht alle fehler ab

5. nach socket schliessen, ist durch den ablauffehler kein fehler mehr gesetzt, und das ganze fängt wieder von vorne an


wenn du das ganze im debugging mode durchläufst , dann dauert der durchlauf so lange, das ein timeout aufgrund der zeit
erkannt wird.

also theoretisch ist mir nun alles klar


was bleibt ist das grundproblem das kein socket eingerichtet werden kann..

werde mir bis morgen einen patch einfallen lassen, damit wir wenigstens eine korrekten fehlermeldung bekommen.

aber soweit so gut .... immerhin konnten wir schon einen bug finden


danke...

peewit

#19
probiere doch mal diese codezeile einzeln aus

diSocket:=SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, 0);


und schau ob das überhaupt funktioniert
das wird bei den netzwerkvariablen auch genauso verwendet

solange das alleine schon nicht geht, hat alles andere sowieso keinen sinn !



EMV-Fuzzi

Hallo peewit!

Das:
PROGRAM PLC_PRG
VAR
diSocket: DINT;
xFlanke: R_TRIG;
END_VAR

xFlanke(clk:=%IX0.12);

IF xFlanke.Q THEN
  diSocket:=SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, 0);
END_IF

funktioniert!

Dabei hat diSocket Werte ab 0x0081F0AC + n * 0xB0 angenommen.
Nach ca. 20 Versuchen habe ich abgebrochen...

Schoen! Wir machen Fortschritte!


peewit

dann probiere das auch aus
ist eigentlich genau das gleiche, so wie im ip_control baustein verwendet


socket := SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_UDP);

EMV-Fuzzi

Hallo peewit,

Jetzt habe ich mal alle Protokolle aus der Variablenliste von SysLibSockets.lib
durchprobiert und komme zu dem Schluss:
Schei..e - da funktioniert ja nur die "0" Fehlerfrei!

Muss mir die Sache mit den Sockets abschminken oder gibt es Kombinationen,
der per Definition nicht funktionieren koennen?

peewit

hallo

ich habe mal eine neue version der ip_control bausteine erstellt, bei der nun ein korrekter Fehlercode
ausgegeben werden sollte.

(ip_control.exp und ip_control2.exp)

also importieren und testen, nun solltest du dann immer den fehler 0x01000000 bekommen

----------------------------------------------

das bei dir nur die 0 funktioniert, ist vielleicht gar nicht so schlimm

dazu habe ich auch eine testversion erstellt
wieder die bausteine importieren
(ip_control_(test).exp und ip_control2_(test).exp)

nun sollten alle socket mit wert 0 erstellt werden

momentan habe ich keine hardware und zeit , es auch zu testen.

probiere es einfach aus.... mehr als nicht funktionieren kann es eh nicht


[gelöscht durch Administrator]

EMV-Fuzzi

Hallo peewit,

nachdem ich nun dazu gekommen bin, ein wenig zu spielen, hier das Ergebnis:

Wie erwartet, bekomme ich beim neuen "ip_control" sofort einen Fehler gemeldet.

Bei der Testversion aus "ip_control_(test).exp" tut sich was auf der Netzwerkleitung!
... und zwar dauerhaft! Die beiden Teilnehmer tauschen fleissig Daten untereinander
aus und beim Errorcode des SNTP-Bausteins erscheint eine 0x0000FE00. Der
Datenverkehr geht auch weiter, wenn die Aktivierung des Bausteins weggenommen
wird und kommt erst zum Erliegen, wenn ich den Baustein erneut aktiviere. Nun steht
der Errorcode auf 0x00000000 und ich bekomme am UDT-Ausgang das Datum/Uhrzeit
des vorigen Aktivierungs-Zyklus. Dies kann ich dann beliebig wiederholen -- es kommt
als Ergebnis immer die Uhrzeit vom vorigen Aktivieren.

Ich habe den Traffic zwischen den beiden Teilnehmern mit tcpdump mitgeschrieben und
als PCAP-Datei hinten angehaengt. Vielleicht kannst Du daraus schlau werden, was hier
schief laeuft...

Ich bin aber schon mal soweit zufrieden, dass ich ueberhaupt mit der Steuerung am
Netzwerk teilnehmen kann! Den Rest kriegen wir auch noch!   ;)






[gelöscht durch Administrator]

peewit

#25
hallo

also am netzwerk selber sieht es super aus
daten werden korrekt gesendet und es gibt auch ein passendes antwort telegramm

trotzdem gibts noch ein problem
ich vermute das sich das datensenden nicht beendet
---------
um auszuschliessen das die letzte änderung (verschluckte fehlermeldung) die ursache ist
habe ich dir einen weiteren ip_control testbaustein angehängt

bitte einmal damit testen, und dann wieder entfernen ausser es klappt dann

----------
so, wie geht es weiter
für solche heikle probleme habe ich eine debug funktion vorgesehen


du öffnest den ip_control baustein du schaust bei den variablen

dort ist dieser auskommentierte block, den du wieder scharfschalten musst

(*LOG_MSG : LOG_MSG;
_debug_enable : BOOL := TRUE;
debug_index : INT;
debug_ID : INT;
debug_lasterror : DWORD;
debug_last_id : INT := 255;
state_last: BYTE;*)


und im programmcode selber , gibt es einige stellen die folgend aussehen
die musst du auch wieder alle scharfschalten , indem du die kommentierung entfernst

(* ---------------------- Debug-Message ----------------------------*)
(*IF _debug_enable THEN
LOG_CL.NEW_MSG := 'IP_SEN SEND_COUNT ~1 -IP_ID ~6';
LOG_CL.PRINTF[1] := DINT_TO_STRING(s_cur_size);
LOG_CL.PRINTF[6] := INT_TO_STRING(debug_ID);
LOG_MSG();
END_IF;*)
(* -----------------------------------------------------------------------------*)


wenn du dann deinen testbaustein wieder laufen lässt
werden einträge in die globalen daten gemacht

online modus: ressource -> globale variablen -> LOG_CL.MSG findest du dann die einträge
diese einträge würde ich gerne haben !!

unter globale contstanten    LOG_MAX : INT := 40;
kannst du noch die anzahl der möglichen meldungen einstellen (ist eine frage des gesamtspeichers)

dann sehen wir weiter .....



[gelöscht durch Administrator]

EMV-Fuzzi

Hallo peewit,

leider hat die Aenderung noch nicht das gewuenschte Ergebnis:
Ich musste die Debug-Meldungen einschalten!

Im Anhang findest Du die gewuenschten 40 Eintraege als Screenshot.
(kann man sowas eigentlich als Plain-Text aus CoDeSys herausbekommen?)

[gelöscht durch Administrator]

peewit

#27
hallo

ich sehe du bist immer noch sehr fleissig !

1. das der erste test nichts brachte , sehe ich als positiv , weil das bestätigt das die letzte korrektur keinen nebeneffekt verursacht hat

2. die msg_option brauchst du nicht dokumentieren , nur die msg texte
3. extra test: verwende eine sntp_server ip-adresse die nicht existiert, somit werden nur telegramme versendet und
   keine empfangen und wiederhole deinen test

   stelle wieder die debug.msg online

----------------------------------------

4. beim datenempfang habe ich zumindest schon mal eine vermutung

bislang werden folgende zustände vom baustein verarbeitet

-1   = keine daten vorhanden (da ich im non-blcoking mode arbeitet)
0    = verbindungsabbruch vom partner
>0  = anzahl der empfangenen daten

so wie es aussieht kommt bei deiner sps aber -5
dies wird falsch interpretiert, und führt zu einem virtuellen datenempfang

im anhang ist wieder eine adaptierte version die du auch testen solltest
verwende nun wieder eine sinnvolle sntp_server ip-adresse

ergebnissse (debug-texte) wieder online stellen

5. könntest du auch einmal einen breakpoint auf zeile 277 setzen , und schauen was bei bytes_received ankommt
    als kontrolle !

->   277 bytes_received := SysSockRecvFrom(socket, ADR(R_BUF.BUFFER), r_count, 0, ADR(sockaddr), SIZEOF(sockaddr));



wenn ich die sps bei mir hätte , wäre vieles einfacher...



[gelöscht durch Administrator]

EMV-Fuzzi

Hallo peewit,

anbei der Screenshot der LOG_CL vom "extra-test". Das Array MSG
ist bis zum Ende mit dem selben Text gefuellt (Zwischenablage01.png).
Obwohl niemand geantwortet hat, meint der Baustein zu viele
Daten erhalten zu haben: ErrorCode = 0x0000FE00

Nachdem ich die Testversion 4 importiert hatte, habe ich versehentlich
zuerst die Debug-Funktion nicht wieder aktiviert und musste feststellen,
dass nun bei jedem Tastendruck (ich habe xTrigger mit einem digitalen
Eingang verknuepft!) eine Zeit vom Server kommt!
Auch beim ersten Aktivieren!

Trotzdem gibt es selbstredend die Debug-Meldungen in Zwischenablage02.
Ich habe den Baustein mehrfach aktiviert - deswegen gibt es mehrere
Eintraege im Array. Ab Position MSG[25] steht nix mehr drin...

Da die Zeile 277 immer ausgefuehrt wird, steht da immer ein Wert drin,
und zwar meistens 0xFFFFFFFA. Wenn ich zwischendurch mal "druecke",
kommt ein paar Zyklen spaeter eine 0x30 an, die spaeter wiederum mit
0xFFFFFFFA ueberschrieben wird.

... und jedes mal die richtige Zeit am Ausgang von SNTP!   :-) :-) :-)

Es sieht so aus, dass wir auf genau der richtigen Spur sind!!!



[gelöscht durch Administrator]

peewit

hallo

also laut debug meldungen würde ich sagen das es mit testversion 4 (zwischenablage02) funktioniert
und anscheinend kommt bei dir auch was vernünftiges beim baustein raus

somit dürften wir die erste hürde überwunden haben
es gibt aber noch mehr zum testen !

udp client   <---- dürfte nun laufen
udp server <---- noch ungetestet
tcp client    <---- noch ungetestet
tcp server  <---- noch ungetestet


ich werde mir die restlichen sachen noch durchschauen und überlegen wie wir es testen !
also irgendwelche einfachen test-programme basteln....


was ist das den überhaupt für eine steuerung ?
hast du eine genaue typbezeichnung