Hallo,
ich habe ein Problem mit einem STM32 und dem LwIP-Stack:
Nach einigen Empfangs-Versuchen meldet die Receiver-Funktion "Out of
Memory". Welcher Speicher ist das und wie lösche ich den?
Folgendes habe ich gemacht:
Als Basis dient ein Example von ST, ein TCP-echo-server.
Den habe ich auf einem STM32F429 Eval Board am laufen.
Das Ganze läuft mit RTOS.
Ich erzeuge eine netconn mit "netconn_new", binde diese an einen lokalen
Port ("netconn_bind") und verbinde mich mit einem Ziel-Gerät
("netconn_connect"). Dann wird ein Befehl mit "netconn_write" an das
Ziel-Gerät geschickt, um eine Antwort anzufordern. Das funktioniert
alles und ab diesem Punkt sendet das Ziel-Gerät zyklisch.
Sobald das nun durchgelaufen ist, beende ich diesen thread, der das
alles gemacht hat und starte die "netconn_recv" Funktion im neuen
Thread.
Nun kommen dort auch ein paar Daten an.
Diese Daten hole ich mit "netbuf_copy" aus dem Buffer der
"netconn_recv"-Funktion. Das sind pro empfangener Nachricht ungefähr 20
Byte...
Das Problem ist, dass nach zwei bis drei empfangenen "Paketen" die
"netconn_recv" Funktion den Error "ERR_MEM" zurückgibt. In der Header
Datei steht "Out of memory error" dabei.
Ich habe versucht, nach dem Lesen der Daten mit "netbuf_free" Platz zu
schaffen. Leider bringt das nichts.
Ich verstehe nicht, welcher Speicher nun voll sein soll und wie ich den
leeren kann... Wie bekomme ich das raus?
Vielen Dank!
Du könntest mal den Heap vergrössern, um zu sehen, ob das Problem sich
verschiebt. Ich bin kein Mensch für RTOS, aber sonst kann man das meist
im Linker Skript justieren. Das ist sicher kein Dauerzustand, kann aber
Hinweise geben.
Generell hast du inkl. CCRam 256kByte, ohne CCRAM (RTOS benutzt den?)
sind dann 192kByte. Sicher nicht die Welt, wenn das Board nicht noch
externen RAM bereitstellt.
dein code würde helfen ...
lwip kopiert die daten in diverse pbufs
beendest du die verindung musst du diese auch wieder freigeben.
warum nicht die Socket API ?
fgd schrieb:> dein code würde helfen ...>> lwip kopiert die daten in diverse pbufs> beendest du die verindung musst du diese auch wieder freigeben.>> warum nicht die Socket API ?
Ich muss gestehen, dass ich nicht sicher bin! :-)
Die netconn habe ich verwendet, weil die im Beispiel geklappt hat.
Vorher hab ich die RAW-API getestet, aber da bin ich gescheitert.
Mir sind die Unterschiede zwischen der netconn und der Socket API nicht
bewusst. Wo kann ich einen Vergleich nachlesen? Aus der Doku werde ich
nicht schlau...
Hier der Codeausschnitt, der empfängt:
1
voidreceive(void){
2
err_terr;
3
structnetbuf*buf;
4
5
while(1){
6
while((err=netconn_recv(conn,&buf))==ERR_OK){
7
if(buf==NULL)
8
{
9
LCD_UsrLog("No Data received!\n");
10
}
11
else
12
{
13
uint8_tdataReceived[16];
14
netbuf_copy(buf,&dataReceived,16);
15
inti=0;
16
for(i=0;i<16;i++){
17
LCD_UsrLog("Received Data: ");
18
LCD_UsrLog("%X\n",dataReceived[i]);
19
}
20
count++;
21
printf("Receive-counter: %d\n",count);
22
printf("Netconn-state: %d\n",err);
23
}
24
}
25
printf("Netconn-ERROR: %d\n",err);
26
osDelay(3000);
27
}
28
}
Nochmal zur Erklärung:
Die Verbindung mit dem Partner wird aufgebaut, und es wird eine
Nachricht geschickt. Ab dann antwortet der Partner zyklisch. Ich beende
den Thread, der die Verbindung aufgebaut hatte und mache einen neuen
Thread, der aus der Fkt. oben besteht. Ab dann kann ich nur zwei bis
drei Antworten empfangen, dann ist der Puffer voll.
Eine Idee, wie ich den leere?
Danke! :-)
Daniel F. schrieb:>> Nochmal zur Erklärung:> Die Verbindung mit dem Partner wird aufgebaut, und es wird eine> Nachricht geschickt. Ab dann antwortet der Partner zyklisch. Ich beende> den Thread, der die Verbindung aufgebaut hatte und mache einen neuen> Thread, der aus der Fkt. oben besteht. Ab dann kann ich nur zwei bis> drei Antworten empfangen, dann ist der Puffer voll.>> Eine Idee, wie ich den leere?> Danke! :-)
Definiere "thread." Die meisten RTOS kennen keine threads, höchstens
tasks. Wenn Du dynamisch neue tasks erzeugst, gehen dabei jedes Mal
zumindestens der task stack und der Speicher für den TCB vom dynamischen
heap weg. Bist Du sicher, dass Du den jeden nicht benutzten task
komplett mit allem dealloziierst, wenn Du ihn nicht mehr benötigst
("beenden" allein reicht bei vielen RTOS nicht zum dealloziieren)?
Selbst wenn Du das tust, kannst Du in Fragmentierungsprobleme laufen.
Der obige Code ist unvollständig. Die Infrastruktur zum Bauen und
löschen deiner "threads" sollte auch noch veröffentlicht werden.
Ruediger A. schrieb:> Daniel F. schrieb:>>>> Nochmal zur Erklärung:>> Die Verbindung mit dem Partner wird aufgebaut, und es wird eine>> Nachricht geschickt. Ab dann antwortet der Partner zyklisch. Ich beende>> den Thread, der die Verbindung aufgebaut hatte und mache einen neuen>> Thread, der aus der Fkt. oben besteht. Ab dann kann ich nur zwei bis>> drei Antworten empfangen, dann ist der Puffer voll.>>>> Eine Idee, wie ich den leere?>> Danke! :-)>> Definiere "thread." Die meisten RTOS kennen keine threads, höchstens> tasks. Wenn Du dynamisch neue tasks erzeugst, gehen dabei jedes Mal> zumindestens der task stack und der Speicher für den TCB vom dynamischen> heap weg. Bist Du sicher, dass Du den jeden nicht benutzten task> komplett mit allem dealloziierst, wenn Du ihn nicht mehr benötigst> ("beenden" allein reicht bei vielen RTOS nicht zum dealloziieren)?> Selbst wenn Du das tust, kannst Du in Fragmentierungsprobleme laufen.>> Der obige Code ist unvollständig. Die Infrastruktur zum Bauen und> löschen deiner "threads" sollte auch noch veröffentlicht werden.
Sicher bin ich nicht. Habe mit RTOS noch nicht so viel gemacht.
Vielleicht liegt mein Problem auch daran...
Hier der Code:
Die Main: (Aus CubeMX erzeugt...)
1
intmain(void)
2
{
3
/* STM32F4xx HAL library initialization:
4
- Configure the Flash prefetch, instruction and Data caches
5
- Configure the Systick to generate an interrupt each 1 msec
Hier habe ich noch den "ReceiverThread" ergänzt. Standardmäßig war da
nur ein Thread. Zuerst war alles in einem Thread. Aber zum Testen der
Speicher Probleme habe ich dann einen neuen Thread erzeugt, weil ich
dachte, dass der das dann schneller abarbeiten kann... Hat daran wohl
nicht gelegen.
Zuerst wird im Startthread "BSP_Config" aufgerufen: (Nur Texte geändert)
1
staticvoidBSP_Config(void)
2
{
3
/* Configure LED1, LED2 and LED4 */
4
BSP_LED_Init(LED1);
5
BSP_LED_Init(LED2);
6
BSP_LED_Init(LED4);
7
8
/* Init IO Expander */
9
BSP_IO_Init();
10
/* Enable IO Expander interrupt for ETH MII pin */
Ich kenne die netconn-API nicht so, aber könnte es nicht sein, dass man
innerhalb des Structs 'buf' noch Speicher für den Empfang allozieren
muss?
Außerdem war bei mir mal ein Problem mit FreeRTOS und Sockets, dass die
Buffer (wie bei Dir 'dataToSend' und 'dataReceived' lokale Variablen
waren. Ich würde sie testweise mal global definieren.
Wie mach ich das mit dem Speicher?
Im struct sehe ich nur ne Adresse, einen Port und zwei Pointer.
Aber stimmt eigentlich... Wo wird denn definiert, wieviel Speicher der
mit dem Buffer bekommt?
Das mit den Variablen werde ich testen...
Für mein Verständnis:
dataToSend bleibt ja immer fest. --> Irrelevant, oder?
dataReceived sollte doch immer überschrieben werden, mit dem letzten
Wert aus dem Buffer, oder?
Wo genau wird receive() aufgerufen? Ich sehe nur die Definition. Oder
wird es automatisch von LwIP gemacht?
Außerdem ist es immer noch nicht offensichtlich, wie der Thread beendet
wird, in der while(1)-Schleife innerhalb von receive() gibt es keine
einzige Stelle, die die Schleife beenden könnte.
Ich sehe auch keine Stelle, wo netconn_delete() aufgerufen wird, nachdem
die Verbindung beendet wurde. Kann es sein, dass dies garnicht passiert?
Daniel F. schrieb:> Ruediger A. schrieb:>> Daniel F. schrieb:>>>>>> Nochmal zur Erklärung:>>> Die Verbindung mit dem Partner wird aufgebaut, und es wird eine>>> Nachricht geschickt. Ab dann antwortet der Partner zyklisch. Ich beende>>> den Thread, der die Verbindung aufgebaut hatte und mache einen neuen>>> Thread, der aus der Fkt. oben besteht. Ab dann kann ich nur zwei bis>>> drei Antworten empfangen, dann ist der Puffer voll.>>>>>> Eine Idee, wie ich den leere?>>> Danke! :-)>>>> Definiere "thread." Die meisten RTOS kennen keine threads, höchstens>> tasks. Wenn Du dynamisch neue tasks erzeugst, gehen dabei jedes Mal>> zumindestens der task stack und der Speicher für den TCB vom dynamischen>> heap weg. Bist Du sicher, dass Du den jeden nicht benutzten task>> komplett mit allem dealloziierst, wenn Du ihn nicht mehr benötigst>> ("beenden" allein reicht bei vielen RTOS nicht zum dealloziieren)?>> Selbst wenn Du das tust, kannst Du in Fragmentierungsprobleme laufen.>>>> Der obige Code ist unvollständig. Die Infrastruktur zum Bauen und>> löschen deiner "threads" sollte auch noch veröffentlicht werden.>
...
>> Hoffe, es passt nun mit dem Code! :-)
Nein, es fehlen die RTOS spezifischen Implementationen der os...()
Funktionen, speziell der osThreadTerminate() Funktion.
Nach grober Durchsicht des Codes scheint es mir, dass Du den typischen
Fehler begehst, Alles in separaten threads machen zu wollen. Das macht
gerade in linearen Protokollen wenig Sinn. Die meisten
Netzwerkprotokolle sind Halb Duplex, und damit braucht man keine
getrennten Sender und Receiver threads (bei vielen OS, z.B. lwip mit
sockets, ist es sogar so, dass Du die selbe Verbindung nicht im mehreren
threads nicht nutzen kannst, ohne in die wunderbare Welt der
Nebenläufigkeitsprobleme bis Oberkante Unterlippe einzutauchen). Da beim
Multithreading die Regel gilt "zu viel ist mindestens genau so schlecht
wie zu wenig," solltest Du Dir über die Architektur ein paar Gedanken
machen.
Deine Applikation ist ein TCP Client, d.h. Du brauchst auch keinen
separaten thread für das Abwickeln der Kommunikation nach etablierter
Verbindung. Bei Servern kann man das machen, wenn man mehrfache
Verbindungen nebenläufig zulassen will, aber bei Clients ist das
komplett unnötig.
Ich weiss, dass ich jetzt etwas Augenrollen in der Forumsgemeinde
erzwingen werde, aber an dieser Stelle ist ein Hinweis auf Kapitel 4 und
6 meines Buches erlaubt. Da gehe ich sehr detailliert darauf ein, wie
man solche Sachen in RTOS umsetzen kann.
Daniel F. schrieb:> Wie mach ich das mit dem Speicher?> Im struct sehe ich nur ne Adresse, einen Port und zwei Pointer.>> Aber stimmt eigentlich... Wo wird denn definiert, wieviel Speicher der> mit dem Buffer bekommt?
Weiß ich leider auch nicht (und wie gesagt auch nicht, ob das überhaupt
notwendig ist)!
>> Das mit den Variablen werde ich testen...> Für mein Verständnis:> dataToSend bleibt ja immer fest. --> Irrelevant, oder?> dataReceived sollte doch immer überschrieben werden, mit dem letzten> Wert aus dem Buffer, oder?
Ob die Variable immer denselben Inhalt hat oder sie immer überschrieben
wird, tut ja bzgl. der Speicherstruktur wahrscheinlich nichts zur Sache.
Einfach mal global ausprobieren!
was mir auffällt ist das du die tasks zwar erstellst aber diese laufen
ins ende
d.h. der Speicher wird ggf nie freigegeben
beim beenden ( wirklichem kill ) musst du dem RTOS auch sagen das er
den speicher freigeben soll.
1
voidTask(void)
2
{
3
bool_tabbruch=0;
4
// tu was vor dem loop
5
6
while(1)
7
{
8
// task lebt so lange im loop bis abbruch gefordert wird
Ruediger A. schrieb:> Nein, es fehlen die RTOS spezifischen Implementationen der os...()> Funktionen, speziell der osThreadTerminate() Funktion.
Da diese Funktionen aus den Examples kommen, habe ich diese nicht
angepackt:
1
osStatusosThreadTerminate(osThreadIdthread_id)
2
{
3
#if (INCLUDE_vTaskDelete == 1)
4
vTaskDelete(thread_id);
5
returnosOK;
6
#else
7
returnosErrorOS;
8
#endif
9
}
Ruediger A. schrieb:> Nach grober Durchsicht des Codes scheint es mir, dass Du den typischen> Fehler begehst, Alles in separaten threads machen zu wollen. Das macht> gerade in linearen Protokollen wenig Sinn.
Ich hatte zuerst alles in einem Thread, dachte aber, dass der zweite
neue und leere Thread schneller sein könnte.... Denkfehler...
Für diese Anwendung brauche ich keine Threads, das ist richtig.
Theoretisch kann das alles linear ablaufen. Allerdings hab ich das ohne
RTOS mit der RAW API probiert und bin gescheitert. Hab dazu keine
Examples gefunden, die ich nutzen konnte...
Sollte also jemand ein Example ohne RTOS haben, wo eine TCP Verbindung
aufgebaut wird und Daten gesendet / empfangen werden, dann als her
damit... :-)
Ist die RAW API dafür geeignet? Macht das Sinn, das damit zu machen?
Peter schrieb:> Wo genau wird receive() aufgerufen?
Das ist der "ReceiverThread" im "StartThread" und läuft parallel. Soweit
ich es verstanden habe...
Peter schrieb:> Außerdem ist es immer noch nicht offensichtlich, wie der Thread beendet> wird, in der while(1)-Schleife innerhalb von receive() gibt es keine> einzige Stelle, die die Schleife beenden könnte.>> Ich sehe auch keine Stelle, wo netconn_delete() aufgerufen wird, nachdem> die Verbindung beendet wurde. Kann es sein, dass dies garnicht passiert?
Das ist richtig. Der Thread soll theoretisch so lange laufen, wie das
System an ist. Wenn der Code läuft, würde ich noch ein reconnect
ergänzen. Das ist aber oben noch nicht implementiert.
Aktuell wird weder der Thread beendet, noch die Verbindung gelöscht!
fgd schrieb:> was mir auffällt ist das du die tasks zwar erstellst aber diese laufen> ins ende> d.h. der Speicher wird ggf nie freigegeben>> beim beenden ( wirklichem kill ) musst du dem RTOS auch sagen das er> den speicher freigeben soll.
Das ist wohl in der "osThreadTerminate" Funktion so implementiert.
Allerdings fällt mir aktuell auf, dass ich die ID übergeben muss, was
ich nicht mache... Der Befehl wurde im Example aufgerufen für den Init
Thread. Dachte der gilt für den jeweiligen Thread....
Daniel F. schrieb:> Ruediger A. schrieb:>> Nach grober Durchsicht des Codes scheint es mir, dass Du den typischen>> Fehler begehst, Alles in separaten threads machen zu wollen. Das macht>> gerade in linearen Protokollen wenig Sinn.>> Ich hatte zuerst alles in einem Thread, dachte aber, dass der zweite> neue und leere Thread schneller sein könnte.... Denkfehler...>> Für diese Anwendung brauche ich keine Threads, das ist richtig.> Theoretisch kann das alles linear ablaufen. Allerdings hab ich das ohne> RTOS mit der RAW API probiert und bin gescheitert. Hab dazu keine> Examples gefunden, die ich nutzen konnte...>> Sollte also jemand ein Example ohne RTOS haben, wo eine TCP Verbindung> aufgebaut wird und Daten gesendet / empfangen werden, dann als her> damit... :-)> Ist die RAW API dafür geeignet? Macht das Sinn, das damit zu machen?>https://www.springer.com/de/book/9783658148492
mittig runterscrollen, link "Zusatzmaterial" klicken, entpacken. Das
Beispiel von Kapitel 7 kannst Du als Blaupause nehmen (allerdings hat
das genau den Fehler, auf denselben socket von 2 threads zuzugreifen,
sh. mein blog für Ergänzungen).
Das raw API kannst Du nehmen, aber Du verlierst auch nichts mit dem BSD
API. Dafür gewinnst Du aber Kompatibilität; gefühlte 90% aller nicht
über high level Abstraktionslayer implementierte TCP/IP Kommunikationen
gehen über das BSD API.
Ruediger A. schrieb:> mittig runterscrollen, link "Zusatzmaterial" klicken, entpacken. Das> Beispiel von Kapitel 7 kannst Du als Blaupause nehmen (allerdings hat> das genau den Fehler, auf denselben socket von 2 threads zuzugreifen,> sh. mein blog für Ergänzungen).>> Das raw API kannst Du nehmen, aber Du verlierst auch nichts mit dem BSD> API. Dafür gewinnst Du aber Kompatibilität; gefühlte 90% aller nicht> über high level Abstraktionslayer implementierte TCP/IP Kommunikationen> gehen über das BSD API.
Danke für die Infos!
Werde mir das Beispiel ansehen...
Ich habe gesehen, dass es eine Neuauflage von dem Buch gibt, welche aber
noch nicht zu kaufen ist. Ab wann wird die Verfügbar sein? Lohnt sich
dann bestimmt nicht mehr, die erste Auflage zu kaufen, oder?
Ruediger A. schrieb:> Das raw API kannst Du nehmen, aber Du verlierst auch nichts mit dem BSD> API. Dafür gewinnst Du aber Kompatibilität; gefühlte 90% aller nicht> über high level Abstraktionslayer implementierte TCP/IP Kommunikationen> gehen über das BSD API.
Mit der RAW-API kann man doch als Gegenstück auch einfach Sockets
benutzen (z.B. einen Windows-/Linux-Client/-Server).
Ruediger A. schrieb:> Definiere "thread." Die meisten RTOS kennen keine threads, höchstens> tasks. Wenn Du dynamisch neue tasks erzeugst, gehen dabei jedes Mal> zumindestens der task stack und der Speicher für den TCB vom dynamischen> heap weg. Bist Du sicher, dass Du den jeden nicht benutzten task
Das kann man interpretieren wie man will. Eine Task in einem Embedded
System mit RTOS entspricht viel eher einem Thread auf einem Posix System
als einer Task/Prozess eines Posix Systems: Auf Embedded Systemen gibt
es meistens keine eigenen Addressbereiche, so das jeder auf alles zu
greifen kann, sowie das bei Threads in einem PC Programm ist, PC
Programme untereinander können im allgemeinen jedoch nicht auf den
gleichen Speicher zugreifen.
Zum Thema:
Generell ist es keine gute Idee in einem Embedded System Tasks/Threads
regelmäßig zu starten und zu beenden. Das führt fast immer zu
Heap-Fragmentierung. Dadurch wird auch nichts schneller. (Sonder eher
langsamer)
Als kleinen Hinweis aus eigener Erfahren: TCP ist nicht dafür ausgelegt,
viele kleine Datenhäppchen unidirektional zu übertragen. Das hängt mit
der Funktionsweise des Protokolls zusammen. (Delayed Ack, Naggle)
Entweder bei kleinen Daten im Ping-Pong Häppchen hin und her schicken
oder große Datenmengen möglichst groß, am Stück dem Stack übergeben.
Wir verwenden die lwip sockets und pbufs direkt. Wenn man sich da erst
mal dran gewöhnt hat, ist das nicht schlecht, da man sich das hin und
her Kopieren an vielen Stellen sparen kann.
Du musst nach netconn_recv(), wenn Du die Daten verarbeitet hast
pbuf_free benutzen um den Puffer wieder freizugeben:
1
structpbuf*p;
2
netconn_recv(..,&p);
3
4
if(NULL!=p)
5
{
6
/* daten benutzen */
7
p->payload...
8
9
pbuf_free(p);
10
p=NULL;
11
}
Edit: Wir verwenden gar nicht die Raw Api, sondern gehen lowlevel auf
die sockets/funktionen drauf.
Moin,
ich würde bei lwip ausschliesslich mit fixen DMA-Buffern arbeiten und
generell darauf hinarbeiten, so wenig wie möglich malloc() zu verwenden.
Das kann allerdings darauf hinauslaufen, dass man sich dann doch einen
eigenen TCP-Stack schreibt, die Architektur des LWIP ist nicht gerade
optimal für DMA-Queues.
Andreas M. schrieb:> Als kleinen Hinweis aus eigener Erfahren: TCP ist nicht dafür ausgelegt,> viele kleine Datenhäppchen unidirektional zu übertragen. Das hängt mit> der Funktionsweise des Protokolls zusammen. (Delayed Ack, Naggle)> Entweder bei kleinen Daten im Ping-Pong Häppchen hin und her schicken> oder große Datenmengen möglichst groß, am Stück dem Stack übergeben.
Unidirektional geht das ohne Probleme, da der Nagle auch kleine
Datenpakete 'queue't. Kann man sich in Wireshark zumindest für den
Linux-Kernel-Stack anschauen, was der LWIP macht, weiss ich nicht. Ist
ja faktisch nur ein Stream. Da kriegt man auch eine anständige Datenrate
hin. Schlechter ist Ping-Pong, das hat dann in UDP mehr Performance.
Fitzebutze schrieb:> Unidirektional geht das ohne Probleme, da der Nagle auch kleine> Datenpakete 'queue't. Kann man sich in Wireshark zumindest für den> Linux-Kernel-Stack anschauen, was der LWIP macht, weiss ich nicht. Ist> ja faktisch nur ein Stream. Da kriegt man auch eine anständige Datenrate> hin. Schlechter ist Ping-Pong, das hat dann in UDP mehr Performance.
Lass mal einen LwIP in der Standard-Config einfach nur 1 byte Packete an
ein Windows senden. Du wirst bei ca ein bis zweistelligen Byte/s
Durchsatz landen. Das Windows sendet auf Packete die unterhalb der MTU
Größe sind erst nach ca. 200ms den Ack (Delayed Ack) weil der Windows
Stack davon ausgeht, das wenn so wenig Daten ankommen, der Sender nichts
mehr senden wird und zunächst die (Windows-) Empfängerapplikation was
zurücksenden will. (Das Ack wird dann zusammen mit den Antwortdaten
verschickt). Der Lwip Puffert aber die Daten solange das Ack noch nicht
angekommen ist. (Wenn man byteweise verschickt gehen dem dann auch bald
die puffer aus): Sobald man in der Windows Applikation anfängt auf die
Empfangenen Daten jeweils mit einer 1Byte Response zu antworten steigt
der Datendurchsatz massiv an, weil die Acks schneller geschickt werden.
Der Linux Netzwerkstack macht das eigentlich auch so, hat aber eine
Heuristik die das Verhalten erkennt und den Delayed Ack abschaltet.
Unter Linux gibt es auch extra Socket Options um diesen Anwendungsfall
(telnet, ssh) zu optimieren.
Deswegen sollte man bei TCP möglichst alle Daten auf einmal versenden
(wenn man kann)
Andreas M. schrieb:> Lass mal einen LwIP in der Standard-Config
Weißt Du vielleicht, was man bei LwIP (STM32) umstellen muss, damit
mehrere Pakete versendet werden können und nicht jedes einzelne durch
ein ACK quittiert werden muss, bevor ein weiteres gesendet wird (bei mir
klappt das partout nicht, auch mit 'tcp_output()' nicht)? TCP/IP an sich
lässt das ja zu. Und LwIp soll das eigentlich lt. deren Forum auch
können.
Daniel F. schrieb:> Ruediger A. schrieb:>> mittig runterscrollen, link "Zusatzmaterial" klicken, entpacken. Das>> Beispiel von Kapitel 7 kannst Du als Blaupause nehmen (allerdings hat>> das genau den Fehler, auf denselben socket von 2 threads zuzugreifen,>> sh. mein blog für Ergänzungen).>>>> Das raw API kannst Du nehmen, aber Du verlierst auch nichts mit dem BSD>> API. Dafür gewinnst Du aber Kompatibilität; gefühlte 90% aller nicht>> über high level Abstraktionslayer implementierte TCP/IP Kommunikationen>> gehen über das BSD API.>> Danke für die Infos!>> Werde mir das Beispiel ansehen...> Ich habe gesehen, dass es eine Neuauflage von dem Buch gibt, welche aber> noch nicht zu kaufen ist. Ab wann wird die Verfügbar sein? Lohnt sich> dann bestimmt nicht mehr, die erste Auflage zu kaufen, oder?
Hallo Daniel,
ich habe das in einem anderen thread aufgegriffen, um diesen nicht OT zu
führen:
Beitrag "Buch "Embedded Controller," ISBN-10 3658148497"
Danke!
Dirk schrieb:> Andreas M. schrieb:>> Lass mal einen LwIP in der Standard-Config>> Weißt Du vielleicht, was man bei LwIP (STM32) umstellen muss, damit> mehrere Pakete versendet werden können und nicht jedes einzelne durch> ein ACK quittiert werden muss, bevor ein weiteres gesendet wird (bei mir> klappt das partout nicht, auch mit 'tcp_output()' nicht)? TCP/IP an sich> lässt das ja zu. Und LwIp soll das eigentlich lt. deren Forum auch> können.
Eigentlich sollte das Nagleing default sein und mit der Option
TCP_NODELAY deaktiviert werden.
Die Frage ist natürlich, welches Zeitverhalten zwischen den kleinen
Paketen herrscht. Wenn Du ein Protokoll hast, bei dem ein peer ein
mehrere wenige Bytes umfassendes Paket schickt (z.B. einen Master-Slave
Polling request), der in der Regel auch nur weinge Bytes gross ist,
möchtest Du nicht wirklich Nageln, da beim Nageln ein Timer aufgezogen
wird, der erst beim Ablaufen alles was in der Zwischenzeit aufgelaufen
ist schickt. Das ist aber mit vielen Protokollen inkompatibel, weil die
gerade auf einen recht schnellen Umlauf getunt sind. Es gibt ausserdem
ein Riesenpotential für subtile Probleme. Wenn z.B. ein serielles
Master-Slave Protokoll 1:1 auf ein Netzwerk übertragen wird, passiert es
oft, dass sich masterseitig Paketretransmissions anstauen, die dann
plötzlich beim Slave en bulk ankommen. Was dann dazu führt, dass ACKs
falsch zugeordnet werden, wenn keine eindeutigen Sequenznummern im
Protokoll definiert sind. BTDT.
Dirk schrieb:> Andreas M. schrieb:>> Lass mal einen LwIP in der Standard-Config>> Weißt Du vielleicht, was man bei LwIP (STM32) umstellen muss, damit> mehrere Pakete versendet werden können und nicht jedes einzelne durch> ein ACK quittiert werden muss, bevor ein weiteres gesendet wird (bei mir> klappt das partout nicht, auch mit 'tcp_output()' nicht)? TCP/IP an sich> lässt das ja zu. Und LwIp soll das eigentlich lt. deren Forum auch> können.
Das ist der Nagle Mechanismus. Der Sorgt dafür das der LwIP bei
tcp_output nichts sendet solange noch ein "Ack" aussteht außer es gibt
mindest noch zwei offene Segmente. Siehe auch "tcp_do_output_nagle".
Kann man abschalten, indem man auf dem socket das TF_NODELAY flag setzt.
dann sollte es bei tcp_output direkt rauskommen:
Andreas M. schrieb:> Das ist der Nagle Mechanismus. Der Sorgt dafür das der LwIP bei> tcp_output nichts sendet solange noch ein "Ack" aussteht außer es gibt> mindest noch zwei offene Segmente. Siehe auch "tcp_do_output_nagle".> Kann man abschalten, indem man auf dem socket das TF_NODELAY flag setzt.> dann sollte es bei tcp_output direkt rauskommen:> tcp_nagle_disable(pcb)>> oder> int optval = 1;>> lwip_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval))
Danke, aber löst wohl nicht mein Problem, denn hiernach
http://lwip.100.n7.nabble.com/TCP-NODELAY-td6837.html
Post 'Oct 15, 2008; 8:31pm'
macht TF_NODELAY dasselbe wie 'tcp_write()' gefolgt von 'tcp_output()',
was bei mir ja scheitert (werde es aber trotzdem in Kürze mal
ausprobieren, denn der Post ist ja von 2008, evtl. hat sich in LwIp
seitdem was geändert).
constcharcontent_http_404[]={"HTTP/1.0 404 Not found\r\nServer: testserver\r\nConnection: Close\r\n\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"};
fgd schrieb:> if( lwip_read(conn, buf , 1460 ) )
das ist aber ein optimistischer Ansatz, da hofft man einen Request am
Stück zu bekommen. Aber das garantiert dir TCP und auch lwip_read nicht.
Johannes S. schrieb:> fgd schrieb:>> if( lwip_read(conn, buf , 1460 ) )>> das ist aber ein optimistischer Ansatz, da hofft man einen Request am> Stück zu bekommen. Aber das garantiert dir TCP und auch lwip_read nicht.
richtig.
deswegen Quick&Dirty
der vollständigkeit halter muss man hier erweitern
Hallo Zusammen.
Weil sich in diesem Thread wohl die Experten der Netzwerkprogrammierung
tummeln, so schließe ich meine Frage gleich zum Thema lwip an,
vielleicht kann mir ja hier jemand helfen :)
Ich habe bereits ein bestehendes Programm, mit dem ich durch einen
ATWINC1500 "callbacks" von socket, recv, send, accept, bind
erhalte...Nun würde ich gern das selbe mit einem ESP32 ohne den
ATWINC1500 realisieren: also lwip & callbacks..
Ist sowas leicht realisierbar?
Danke & schönen Abend :)
Alexander M. schrieb:> also lwip & callbacks
Du hast beide Antworten in deinem Thread schon bekommen? Entweder nimmst
du FreeRTOS mit Callbacks oder gehst Socket mit Select (und rufst deine
Callbacks selber auf).
Ja schon, nur bin ich noch nicht ganz glücklich mit der aktuellen
Antwort ..
1. Ich würde gern in EINEM Task als Server mehrere Services abarbeiten
--> FreeRTOS würde in diesem Fall ausscheiden
2. Timeout mit "select" geht meiner Meinung nach nur mit recv / send -->
ich benötige accept aber auch noch ...
Mir erscheint das so in meinem Fall nicht realisierbar...
Vielleicht noch eine Zusatzfrage:
Wo gibt es denn gute Dokumentation über lwip, gibt's sowas überhaupt,
oder gilt lwip zum Themengebiet Socketprogrammierung /
Netzwerkprogrammierung und lehnt sich an deren (sehr zahlreichen)
Dokumentationen an?
Auf einem Posix-System geht "select" natürlich auch für den server
socket für "accept". Dafür nimmt man den server socket in die read_fds
rein. Sobald eine Verbindung eingegangen ist, kommt select dann mit
POLL_IN für den server socket zurück. (Bezeichnungen evtl. falsch, ich
benutze meistens poll())
Ich weis jetzt nicht wie die Unterstützung beim Lwip dafür ist. Ich
scheue mich allerdings davor den ganzen overhead der posix api im
embedded Bereich mitzunehmen, wir benutzen immer die callbacks.
Alexander M. schrieb:> 1. Ich würde gern in EINEM Task als Server mehrere Services abarbeiten> --> FreeRTOS würde in diesem Fall ausscheiden
Das verstehe ich nicht. Wenn man schon ein FreeRTOS im Einsatz hat, kann
man natürlich den ganzen Lwip plus die Server in einer einzigen Task
laufen lassen. Z.b. wenn man die Callbacks nutzt. Außerdem kann man den
Lwip Prozess auch mitbenutzen indem man Timeout callbacks startet.
Wenn man gar kein RTOS hat, dann kann, bzw. muss man eine bestimmte
Funktion (Namen hab ich vergessen) regelmäßig aus seiner Hauptschleife
raus aufrufen. Ist auch kein Hexenwerk.
Alexander M. schrieb:> Ja schon, nur bin ich noch nicht ganz glücklich mit der aktuellen> Antwort ..> 1. Ich würde gern in EINEM Task als Server mehrere Services abarbeiten> --> FreeRTOS würde in diesem Fall ausscheiden
Das ist eine etwas unklare Aussage. Meinst Du damit, dass Du am liebsten
in mehreren threads derselben Task nebenläufig Anfragen an der Server
abarbeiten würdest und FreeRTOS deswegen ausscheidet, weil es nur
multitasking, aber kein multithreading unterstützt?
Du könntest mal gucken, ob FreeRTOS Coroutinen Dir dabei weiter helfen.
Andernfalls müsstest Du natürlich auf ein echtes Multithreading OS
umsteigen, aber was da in Frage kommt, hat schon einen wesentlich
höheren Grundfootprint als FreeRTOS. Einen Tod muss man sterben...
Die beste Architektur zum nebenläufigen Abarbeiten von mehreren offenen
I/O operationen sind I/O completion ports. Die gibt es aber meines
Wissens nach nur unter einem Betriebssystem, das hier eher unpopulär
ist...
Hallo Zusammen.
Leider hab ich die letzten beiden Artikel nicht ganz verstanden,
vielleicht ist das aber tatsächlich nah mit der Lösung meines Problems
verbunden.
Deshalb würde ich gern nochmals mein Problem "genauer" schildern:
Ich habe 3 Tasks:
HTTP, HTTPS:
Hier sollen "Anweisungen" an den CONTROL task erfolgen, z.B. "Erstelle
ein Socket", "Empfange Daten", "Sende Daten"
CONTROL:
Wartet auf Anweisungen (Pollt), und bei einer "eingegangen" Anweisung
(z.B. "accept"-Anweisung vom HTTP Task) erfolgt im CONTROL task eine
Abarbeitung dieser Anweisung:
accept(socket_id, socket_address, socket_length);
In diesem Fall würde aber jetzt der CONTROL Task solange warten, bis
das accept vom http-service erfolgreich war (blocking). Eine
"gleichzeitige" Abarbeitung der Anweisungen ist somit nicht möglich.
Mein Ziel ist es aber, die Service HTTP & HTTPS gleichzeitig zum laufen
zu bekommen.
Mit einer Art "callbacks" würde ich dieses Problem umgehen, z. B.:
accept(socket_id, socket_address, socket_length, CALLBACK);
Leider gibt's sowas aber meiner Meinung nach nicht...
Grüße & schönen Abend :)
das Konzept hört sich komisch an. HTTP und HTTPS sind doch zwei
verschiedene Ports und da macht man zwei Threads mit je einem eigenen
socket und accept(). Wenn accept einen client socket liefert kann der an
einen oder mehrere Workerthreads übergeben werden, diese müsste man für
HTTP und HTTPS gleich machen können.
Ja, da geb ich dir schon Recht, das klingt auf dem ersten Blick nicht
ganz überzeugend, die Frage ist aber trotzdem:
Wäre diese Abarbeitung irgendwie möglich, z.B. durch Implementierung
eines Callbacks?
Grüße :)
So prinzipiell ja. In Mbed gibt es ein socket.sigio wo ein callback auf
socket events registriert werden kann:
https://os.mbed.com/docs/mbed-os/v5.15/mbed-os-api-doxy/class_socket.html#a59ccc5950bb6b32b712444b2a92c0631
Mbed benutzt auch den Lwip Stack, wenn man sich durch die Quellen wühlt
müsste man den Ansatzpunkt finden.
Laut Doku ist das aber dünnes Eis. Da müsste man mit einer MessageQueue
arbeiten die auch aus einer ISR gefüttert werden darf. Wollte ich auch
schon mal machen, ein Webserver mit vielen threads ist sehr
Ressourcenhungrig.
Danke für die Info, aber ich glaube, das ist mir aktuell dann doch ne
Nummer zu hoch. Schade, dass es keine "einfache" Lösung gibt... :D
Grund der Frage ist Folgende:
Ich habe eine bereits funktionierende Implementierung mit einem
ATWINC1500, der über ein Bussystem "Events" (accept, send, ...) an den
Haupt-uC sendet. Dieser arbeitet dann diese Events in einem Callback ab.
Eine ähnliche "Callback"-Funktionalität hätte ich gern auf meinem
ESP32...
Doku:
https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/lwip.html
Grüße :)
socket port 80 im task 1
socket port 443 im task 2
deine control geschichte im task 3
scheinbar hast du noch nicht ganz verstanden wie das mit den RTOs tasks
funktioniert
es ist der sinn dahinter das eine funktion blockieren kann und das auch
teilweise SOLL ( -> idle 0% auslastung wenn nichts passiert )
du musst deine sockets erstmal grundsätzlich so schreiben das sie das
tun was sie sollen ..
Daten empfangen und das was du benötigst an den control task
weiterleiten
( hier werfe ich mal mailbox in die runde )
im prinzip wartet dein controltask auf einen eingang der mailbox
dieser Task wacht endlich mal auf und arbeitet die Daten ab
wenn du nur eine einzige info hast für einen Taks um den aufzuwecken
( zB DMA transfer abgeschlossen -> tu was mit daten ) reicht eine
Tasknotification aus .
wenn du aus merhreren tasks was abarbeiten sollst ( statemaschine )
dann mailbox
diese mailbox fütterst du mit den daten für deinen controltask
Der http oder https arbeiten indessen weiter eingehende daten ab
( priorisierung )
Ist der controltask mal an der reihe arbeitet er die daten ab und legt
sich wieder schlafen
prinzig des RTOs ist dann nur den task aufzuwecken ( wenn auch nur für
eine runde in der loop ) wenn etwas passiert
sonst liegen alle tasks im dauerschlaf
was auch funktioniert ist eine zykische unterbrechung
Danke für den interessanten Input :)
Ich würde aber trotzdem (und dieses Mal zum allerletzten Mal) nochmals
die Frage in die Runde stellen, ob die Abarbeitung verschiedener
Services in 1 Task wirklich nicht möglich ist? Ob sinnvoll oder nicht
ist erstmal ein anderes Thema...
Also:
Kann ich 2 Services (HTTP + HTTPS) über 1 Task laufen lassen, ist das
theoretisch möglich mit der lwip library? Wenn ja, bitte bitte mit
kleinem Gedankenbeispiel aufzeigen...
Danke :)
Alexander M. schrieb:> Auf die Wiki Seite bin ich natürlich nicht gekommen
Da leitet dich der Autor von lwIP (Adam Dunkels) hin, wenn du auf seine
Homepage gehst. Hast du wirklich gesucht?
Hmm
Grundsätzlich wäre das doof ...
Wenn man 2 Abarbeitungen hätte wäre der Overhead da zu filtern wo es Her
kam
Oder das Accept wo gerade nichts kommt blockiert die Abarbeitung
teilweise
Das select muss auch gepollt werden und würde ggf etwas Zeit in Anspruch
nehmen.
Ich habe das bei einem UDP Service laufen weil es nur entweder von A
oder von B kommen kann
Aber nie von beiden.
Das ist aber ein Spezialfall !!!
Bei http oder https .. würde ich immer getrennte Tasks laufen lassen.
Die payload gut vorfiltern und das dann dem Controltask per Mailbox
überreichen
Alexander M. schrieb:> Danke für den interessanten Input :)>> Ich würde aber trotzdem (und dieses Mal zum allerletzten Mal) nochmals> die Frage in die Runde stellen, ob die Abarbeitung verschiedener> Services in 1 Task wirklich nicht möglich ist? Ob sinnvoll oder nicht> ist erstmal ein anderes Thema...>> Also:> Kann ich 2 Services (HTTP + HTTPS) über 1 Task laufen lassen, ist das> theoretisch möglich mit der lwip library? Wenn ja, bitte bitte mit> kleinem Gedankenbeispiel aufzeigen...>> Danke :)
Nochmal:
Bist Du mit dem Kontrollflussmodell in TCP (oder in deinem Fall auf
höherer Schicht HTTP(s)) Netzwerkkommunikationen vertraut? Speziell,
bist Du Dir darüber bewusst, dass jede Instanz einer serverseitigen
Kommunikation (in deiner Terminologie "Services") applikationsseitig
einen Verbindungsversuch eines clients explizit annehmen ("accept") und
diesen dann sequentiell (d.h. Empfang des GET requests folgend von der
Antwort über derselben logischen TCP Verbindung) abarbeiten muss?
Wenn ja, solltest Du die Frage eigentlich selber beantworten können. Es
geht genau dann, wenn Du in deiner einen task selber einen Grad von
Nebenläufigkeit zwischen den beiden Kommunikationsinstanzen erzeugen
kannst, d.h. die beiden Instanzen so wechselseitig abarbeiten kannst,
dass die jeweiligen clients in einer akzeptablen Zeit eine Antwort auf
ihre requests kriegen. Das geht z.B. wie von dem/der KollegIn mit dem
langen Namen geschildert wenn Du eine eigene message pump mit
Zustandsautomaten für jede Verbindung baust. Allerdings kann/wird es
dann immer noch passieren, dass eine längere CPU Auslastung (z.B. bei
der Berechnung der Antwort auf einen GET request) den anderen Service
unvorhersehbar und/oder unakzeptabel lange ausbremst.
Warum genau willst Du auf das Multitasking verzichten?
P.S. Wenn ich so deine Ausführungen lese, scheinst Du so ein bisschen
ein unklares Verhältnis von services zu haben. In Kontrollflussbegriffen
sind nicht HTTP und HTTPS verschiedene entities, sondern a) der
thread/task, der eine Verbindung annimmt und b) der sie abarbeitet,
jetzt mal unabhängig, ob das eine HTTP, FTP, POP oder welche immer
andere Nutzdatenkommunikation das ist. In Unix/Linux gibt es da z.B. den
Inet Dämon, der für die Annahme von Verbindungen und deren Weiterleitung
an protokollspezifischen tasks verantwortlich ist, und die Prozesse, die
dann die so entgegengenommenen Verbindungen abarbeiten.
Mit einem Posix like API sollte das gehen wenn die sockets non blocking
gesetzt werden. Dann muss aber mit polling gearbeitet werden wenn das OS
keine callbacks vorgesehen hat, und das war ja die Frage.
Das MT bringt evtl. einen Vorteil indem es die Rechenzeit gerechter
verteilt, kostet dafür mehr Speicher für den Stack der per Thread
gebraucht wird.
Ruediger A. schrieb:> In Unix/Linux gibt es da z.B. den> Inet Dämon, der für die Annahme von Verbindungen und deren Weiterleitung> an protokollspezifischen tasks verantwortlich ist, und die Prozesse, die> dann die so entgegengenommenen Verbindungen abarbeiten.
Wobei man ehrlicherweise ergänzen sollte, dass der inet Dämon ein
historisches Relikt ist, das in der Praxis kaum noch benutzt wird. Die
meisten Anwendungen, erledigen dessen Aufgaben inzwischen lieber selber.
Nichts desto Trotz funktioniert der inet Dämon natürlich immer noch und
ist ein einfaches Hilfsmittel, um mal eben schnell einen Webservice auf
basis simpler Eingabe/Ausgabe auf stdin/stdout zu basteln, ohne sich mit
Netzwerk-Bibliotheken auseinander zu setzen.
Danke euch ;)
Ja da gibt es noch einiges an Grundverständnis zu lernen...
Vermutlich werde ich dann doch, wie bisher zum großen Teil
vorgeschlagen, die Instanzen der serverseitigen Kommunikation über
mehrere Tasks laufen lassen:
Beispiel:
HTTP-task mit accept, recv, ...
HTTPS-task mit accept, recv, ...
...
Vielleicht eine kurze Bestätigung, ob das so vorgeschlagen wurde, damit
ich das wirklich richtig verstanden habe.
Danke & Schönen Abend :)
Du kannst auch drei Tasks machen: HTTP, HTTPS und die eigentliche Logik.
Der HTTP-Task kümmert sich um accept, recv und send für
unverschlüsselten Kram. Der HTTPS-Task kümmert sich um accept, recv und
send für verschlüsselten Kram. Der dritte Task bekommt von den beiden
anderen Tasks die Requests, parst die und schickt die Antwort an den
jeweiligen Task zurück.
Damit kannst du die eigentliche Programmlogik vom verwendeten Protokoll
trennen und es ist egal, ob die Anfrage nach "/super.txt" nun über HTTP
oder HTTPS reinkam.
S. R. schrieb:> Du kannst auch drei Tasks machen: HTTP, HTTPS und die eigentliche Logik.>> Der HTTP-Task kümmert sich um accept, recv und send für> unverschlüsselten Kram. Der HTTPS-Task kümmert sich um accept, recv und> send für verschlüsselten Kram. Der dritte Task bekommt von den beiden> anderen Tasks die Requests, parst die und schickt die Antwort an den> jeweiligen Task zurück.>> Damit kannst du die eigentliche Programmlogik vom verwendeten Protokoll> trennen und es ist egal, ob die Anfrage nach "/super.txt" nun über HTTP> oder HTTPS reinkam.
Im Zusammenhang mit non blocking accepts wäre das denkbar und würde so
eine Art IO Completion Ports für arme Leute implementieren (allerdings
nur mit einem worker thread für die Arbeit zwischen GET und RESPONSE und
funktionsgebundenen threads). Nur:
Jede client transaction ist nach wie vor durch die strikt lineare
Sequenz accept->recv GET->parse GET->compute answer->generate
RESPONSE->send response bestimmt, d.h. die "worker threads" (in deinem
Fall der eine) kann Convoyeffekte erzeugen, bei denen der Rundumlauf
jedes clients von dem der anderen clients abhängen.
Dieser Flaschenhals liesse sich vermeiden, indem man für die "worker"
einen thread pool beiseite stellt, so dass mit jeder request Abarbeitung
ein freier thread aus dem pool aufgeweckt wird. Wenn man das Ganze so
generisch macht, dass so ein worker thread wahlweise IO von TCP oder
worker computations abarbeiten kann, hat man vollständige IO Completion
ports (die beste Art und Weise, Server zu implemntieren).
Ausserdem (mal unabhängig von den verschiedenen Lösungsvorschlägen): Es
wird hier immer impliziert, dass der Unterschied zwischen HTTP und HTTPS
nur ein kleines detail ist so wie zwischen dem Umschalten einer UI mit
rotem und blauen Hintergrund. Das stimmt so nicht. HPPTS ist für die
meisten Embedded Systeme nicht realistisch implementierbar. Das liegt im
Footprint (SSL ist nicht nur ein Protokoll, sondern eine
Protokollhierarchie), in der Rechenkapazität (man braucht asymmetrische
Verschlüsselung, was für kleinere Prozessoren ohne Cryptocoprozessoren
extrem rechenzeitintensiv ist) und Infrastruktur (für PKA ist ein Zugang
zu den Certificate trust chains nötig, was wieder einen Riesenschwanz an
Code nach sich zieht). Wer so etwas will, ist mit einem RTOS auf Cortex
M in aller Regel schnell am Ende und wird auf einen Cortex A mit
Embedded Linux oder kompatibel umsteigen müssen.
Ruediger A. schrieb:> Ausserdem (mal unabhängig von den verschiedenen Lösungsvorschlägen): Es> wird hier immer impliziert, dass der Unterschied zwischen HTTP und HTTPS> nur ein kleines detail ist so wie zwischen dem Umschalten einer UI mit> rotem und blauen Hintergrund.
Der Unterschied ist nur das kleine Detail, dass zwischen den ein- und
ausgehenden TCP-Daten und der verarbeitenden Schicht ein Krypto-Layer
sitzt.
Wichtig ist der Grund, aus dem man HTTPS bzw. Verschlüsselung haben will
(oder muss). Sicherheit ist nicht immer das relevante Kriterium. Die
Entwicklung geht dahin, unverschlüsselte Verbindungen aus Prinzip
abzulehnen - also muss das System verschlüsseln können.
Wenn man damit leben kann, dass der kleine Prozessor pro Anfrage
vielleicht eine Sekunde Bedenkzeit braucht - was für eine Statusseite
einer Steuerung völlig ausreicht - dann braucht man da nicht mit einem
Quadcore draufschießen. Und wenn die Anforderungen steigen, dann wird
man auch in den mittelgroßen Chips ein bisschen AES-Silizium sehen.
Die TLS Implementierung in Mbed (für Cortex-M) gibt es schon lange und
auch der ESP nutzt die mbedTLS. Es geht also durchaus, ist nur auch
speicherhungrig. Und darum würde m.M.n. eine Eventbasierte vs.
Threadbasierte Lösung Sinn machen. So ist auch der Ansatz in Nodejs um
das C10k Problem zu eliminieren. Der µC wird natürlich nicht solche
Anforderungen erfüllen müssen, aber Events statts threads haben ihren
Charme.
Ruediger A. schrieb:> Ausserdem (mal unabhängig von den verschiedenen Lösungsvorschlägen): Es> wird hier immer impliziert, dass der Unterschied zwischen HTTP und HTTPS> nur ein kleines detail ist so wie zwischen dem Umschalten einer UI mit> rotem und blauen Hintergrund. Das stimmt so nicht. HPPTS ist für die> meisten Embedded Systeme nicht realistisch implementierbar. Das liegt im> Footprint (SSL ist nicht nur ein Protokoll, sondern eine> Protokollhierarchie), in der Rechenkapazität (man braucht asymmetrische> Verschlüsselung, was für kleinere Prozessoren ohne Cryptocoprozessoren> extrem rechenzeitintensiv ist) und Infrastruktur (für PKA ist ein Zugang> zu den Certificate trust chains nötig, was wieder einen Riesenschwanz an> Code nach sich zieht). Wer so etwas will, ist mit einem RTOS auf Cortex> M in aller Regel schnell am Ende und wird auf einen Cortex A mit> Embedded Linux oder kompatibel umsteigen müssen.
ist auch ein irrglaube
ich habe einen M7 mit 14-20 tasks am laufen inkl dynamischerm Speicher
Das ding macht vieles... inkl einer TLS verbindung ( dynamisch auf/abbau
)
Das läuft eher als hintergundrauschen.
Habe aus Sicherheitsbedenken alles unter TLS 1.2 deaktiviert.
Damit bleiben nur schlüssel >=256bit und alle halbwegs brauchbaren
verfahren übrig.
Ja der handshake dauert vlt 200-300ms ...
Die Daten selbst sind kein Problem.
fgd schrieb:>> ich habe einen M7 mit 14-20 tasks am laufen inkl dynamischerm Speicher>> Das ding macht vieles... inkl einer TLS verbindung ( dynamisch auf/abbau> )> Das läuft eher als hintergundrauschen.> Habe aus Sicherheitsbedenken alles unter TLS 1.2 deaktiviert.> Damit bleiben nur schlüssel >=256bit und alle halbwegs brauchbaren> verfahren übrig.>>> Ja der handshake dauert vlt 200-300ms ...> Die Daten selbst sind kein Problem.
Welcher POD ist das? Vermutlich mit Crypto Coprozessor?
Auf einem STM32F429 dauert ein asymmetrischer Handshake >>10 Sekunden,
ich bin für jeden Tipp dankbar, das schneller zu kriegen... Danke!