mikrocontroller.net

Forum: PC-Programmierung String Transmission Protocoll mit posix sockets


Autor: Stefanie B. (sbs)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

da ich ein größeres Projekt plane, welches übers Netzwerk läuft habe ich 
mir die posix Sockets angeschaut.

Ich brauche eine zuverlässige Verbinung, die Datagramme(einzele Pakete, 
zb Strings) verschicken kann.

Da dort nur Streams zuverlässig funktioneren (jedenfalls habe ich nichts 
dergleichen gefunden), habe ich die Funktionalität selbst eintwickelt 
und das ganze hochtrabend "String Transmission Protocoll" genannt. ;-)

Hier ein kleiner Ausblick:
stp_connection* stp_connect(char* host, int port);

void stp_accept_connections(int port, void callback(stp_connection* new_connection));

char* stp_recv(stp_connection* stp );

int stp_send(stp_connection* stp, char* line);

void stp_shutdown(stp_connection* stp );

Im Anhang sind die Sourcen dafür, sowie zwei Testprogramme.

Einen kleine Fehler gibt es noch im Server Testprogramm:
Durch die Verwendung von pthreads wird Speicher allokiert, den ich nicht 
freigeben kann(finde keinen pointer dafür :( ).

Ich bitte um Kommentare (Funktionalität, API, Programmierstil, etc.).

Viele Grüße
Stefan Beller

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hier
      if(! (stp->offset < stp->maxSize)){  
        char* newwaitingline;
        newwaitingline = (char*)malloc(stp->maxSize*2*sizeof(char));
        memmove(newwaitingline,stp->waitingline,stp->maxSize);
        free(stp->waitingline);
        stp->waitingline=newwaitingline;
        stp->maxSize*=2;
      }

also die Vergrößerung des Buffers, hättest du auch billiger bekommen 
können. Stichwort: realloc
realloc vergrößert den Buffer, falls das möglich ist. Wenn es dabei 
ausnutzen kann, dass es im Speicher hinter dem Buffer brachliegenden 
Speicher mitbenutzen kann, dann wird es das tun und sich so das 
Umkopieren der Daten sparen. Andernfalls allokiert realloc neuen 
Speicher und erledigt auch das Umkopieren.


    switch(bytes_sent){
...
      case -1:
        /*an error occured, return 1 to indicate*/
        return 1;
        break;

Hmm. Denkst du nicht, dass du zumindest versuchen solltest, den 
Empfänger zu benachrichtigen?
Wenigstens soweit, dass du den Empfänger durch Übermittlung einer '\0' 
aus seiner Warteschleife rauslässt.


Für eine Basis-Lib fehlt mir da die Abfrage von Fehlern. Du benutzt 
malloc als ob du unendlich viel Speicher hättest. Für eine Lib-Funktion 
ist das aber nicht akzeptabel. Der Returnwert von malloc muss abgefragt 
werden und, viel spannender, man muss sich etwas überlegen wie es weiter 
gehen soll, wenn man keinen Speicher mehr hat. Akzeptabel ist fast 
alles, nur eines nicht: Das das Programm deswegen crasht bzw. 
anderweitig Daten zerstört.

Aus diesen und ähnlichen Gründen wird daher bei Übertragungen gerne die 
Länge des nun folgenden Datensatzes zuerst übertragen. Denn dann kann 
sich der Empfänger einen entsprechend großen Buffer zurechtlegen. Die 
Länge hat zwar den Nachteil, dass man einen Datentyp dafür vereinbaren 
muss, auf der anderen Seite wiegt aber der Vorteil, dass der Empfänger 
weiß was auf ihn zukommt, vieles auf.

Autor: Stefanie B. (sbs)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Okay,

ich habe das Ganze ein wenig umgeschrieben.
Man muss zum Verbindungsaufbau nicht mehr angeben wie lang der längste 
String ist, sondern am Anfang jeder Übertragung wird die Länge 
übermittelt.

Das reallocate habe ich auch eingebaut.
(Dieses wird ohnehin nur im Fehlerfall aufgerufen.)

Alle malloc-Fehler werden auch abgefangen.


Nun den zweiten Punkt, den Karl Heinz ansprach, habe ich so umgebaut, 
dass eine Fehlermeldung geworfen wird.

Gegenfrage: Wie teile ich dem Gegenüber mit, dass bei mir irgendetewas 
nicht stimmt, wenn der Fehler darin besteht, das die send-Funktion nicht 
ordnungsgemäß funktioniert?
    switch(bytes_sent){
...
      case -1:
        /*an error occured, return 1 to indicate*/
        perror("stp_send");
        return 1;
        break;


Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:

> Gegenfrage: Wie teile ich dem Gegenüber mit, dass bei mir irgendetewas
> nicht stimmt, wenn der Fehler darin besteht, das die send-Funktion nicht
> ordnungsgemäß funktioniert?

Das ist natürlich eine gute Frage und hängt auch davon ab, warum genau 
eigentlich send das Versenden der Daten verweigert hat.

Jetzt fängt die Sache nämlich an komplizierter zu werden. Wie eigentlich 
meistens wen Fehlerbehandlung ins Spiel kommt :-)

Autor: sebastians (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Gegenfrage: Wie teile ich dem Gegenüber mit, dass bei mir irgendetewas
> nicht stimmt, wenn der Fehler darin besteht, das die send-Funktion nicht
> ordnungsgemäß funktioniert?

Z.B. indem du einen Watchdog nicht mehr triggerst.

Autor: Stefanie B. (sbs)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

so ich habe ein wenig an dem API herumgespielt.

send/recv sind threadsafe, dh. jeweils mit einem Mutex geschützt.

Das serverseitige stp_accept_connections läuft auch mit threads, sodass
diese Funktion nicht blockiert.
Damit ist dann zb so etwas möglich:
  a = stp_accept_connections(port, &callback);  
  sleep(180);//warte 3 Minuten  
  stp_stop_accepting(a);//es werden keine neuen eingehenden Verbindungen akzeptiert.


Nun Fehlerbehandlung, wer mag sie nicht ? ;-)

Ich habe das soweit abstrahiert, dass man entweder senden/empfangen kann 
oder nicht. Also der Systemzustand ist relativ binaer: funktioniert oder 
funktioniert nicht.

Natürlich geht nichts in der Bibliothek derart schief, das das Programm 
crashed, sondern es wird nur per Rückgabewert mitgeteilt, das die 
Verbindung defekt ist.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.