Laden...

Eigenes "Protokoll" schreiben

Erstellt von Fabian vor 18 Jahren Letzter Beitrag vor 18 Jahren 11.664 Views
Fabian Themenstarter:in
1.985 Beiträge seit 2004
vor 18 Jahren
Eigenes "Protokoll" schreiben

Guten Morgen Forum,

ich habe vor, mir ein kleines "Protokoll" zu schreiben. Es geht mir jetzt nicht darum, TCP/IP neu zu schreiben, sondern ein kleines Protokoll mit Handshake, dass darauf aufsetzt und ein paar Daten zwischen zwei Anwendungen austauscht.

Jetzt will ich nicht (wie sonst immer 🙂), einfach drauflos programmieren, sondern mir erstmal die Grundlagen aneignen, worauf bei so einen Protokoll alles zu achten ist und welche Fehler man vermeiden soll.

Für Tipps und Tricks und evtl. Anregungen zu Lektüren wäre ich sehr dankbar.

Grüße,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

4.221 Beiträge seit 2005
vor 18 Jahren

Solange eine Verbindung über TCP besteht werden alle Pakete vollständig und in der richtigen Reihenfolge am Ziel ankommen. (Prüfsummen und Sequenznummern gibst ja schon im Protokoll)...

Also im Prinzip brauchst Du nur noch einen Handshake dass der Empfänger bestätigt dass er etwas erhalten hat (und auch was)....

Man könnte z.B: im Header (bevor Nutzdaten übertragen werden die Länge und eine eigene Sequenznummer implementieren und diese nach dem Empfang überprüfen und zurücksenden)

A --> B #Data#000001#000100#Dies ist ein Test mit 100 Zeichen

B prüft ob er alle 100 Zeichen erhalten hat und sendet dann z.B:

B --> A #OK #000001#000100#

als Bestätigung zurück

A kann dann nach Erhalt der Quittung das Paket 000001 aus seiner Sendqueue entfernen.

Kommt halt darauf an was Du übertragen willst.... Daher dies nicht als das Ei des Kolumbus betrachten, sondern nur als Idee wie man so was implementieren könnte

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

I
72 Beiträge seit 2005
vor 18 Jahren

hi,

also sowas hab ich früher mal mit native C gemacht, ich kenn mich mit C# jetzt
nicht gut genug aus um zu wissen, ob du da selbst Pakete und Streams
erstellen kannst, aber eventuell bist du mit native C bei sowas besser
aufgehoben.

Im Prinzip willst du ja nur auf TCP aufsetzten, d.h. deine Pakete werden
wohl einfach einen Ethernet, IP und TCP layer haben, die Daten kannst du
über den "payload" der TCP pakete dann versenden, das ist eigentlich keine
so grosse Sache (zumindest auf Unix).

Wenn du z.B. eine kleine Client/Server Anwendung machen möchtest,
bei der beliebige Daten A von Rechner A1 an den Server B auf Rechner B1
geschickt werden, brauchst du kein "eigenes Protokoll", da verwendest
du einfach TCP auf einem von dir gewähltem Port und versendest die
Daten über den Payload (= Daten in einem TCP Paket). Die arbeit hast
du dann primär damit das TCP Template zu erstellen und die Daten
sinvoll zu übertragen/auszulesen.

Hier z.B. ein TCP Handshake mit LIBNET (=sehr geil für sowas!) unter Unix:


#if (HAVE_CONFIG_H)
#include "../include/config.h"
#endif
#include "./libnet_test.h"

void dump(char *buf, int max)
{
    int counter = 0;
    for (counter = 0; counter<max; counter++) 
	printf("0x%02x ", buf[counter]&0xff);
    printf("\n");
}

int
main(int argc, char **argv)
{
    int c;
    char *cp;
    libnet_t *l = NULL;
    char *device = NULL;
    libnet_ptag_t tcp, ip;
    u_char *payload;
    u_short payload_s;
    u_long src_ip, dst_ip;
    u_short src_prt, dst_prt;
    char errbuf[LIBNET_ERRBUF_SIZE];
    struct libnet_tcp_hdr *synack;
 
    pcap_t *handle;
    struct bpf_program filter;
    bpf_u_int32 mask;
    bpf_u_int32 net;
    struct pcap_pkthdr header;
    u_char *packet = NULL;
    u_char last;
    char keep_waiting = 1;
    int answer;

    printf("libnet 1.1 packet answering: TCP[raw]\n");
    printf("Send a TCP SYN, wait for the SYN|ACK, and then send the ACK\n");
    printf("Hit CTRL+C to exit if the packet is never detected\n");

    if (argc < 2)
    {
	fprintf(stderr, "Error: first arg must always be your iface name\n");
	usage(argv[0]);
	exit(EXIT_FAILURE);
    }

    /*
     *  Initialize the library.  Root priviledges are required.
     */
    device = argv[1];
    l = libnet_init(
            LIBNET_RAW4,                            /* injection type */
            device,                                 /* network interface */
            errbuf);                                /* errbuf */

    if (l == NULL)
    {
        fprintf(stderr, "libnet_init() failed: %s", errbuf);
        exit(EXIT_FAILURE);
    }

    /*
     * Initialize pcap
     */
    handle = pcap_open_live(device, BUFSIZ, 1, 0, errbuf);
    if(!handle)
    {
	fprintf(stderr, "pcap_open_live(): can't open device [%s]\n", errbuf);
        exit(EXIT_FAILURE);
    }

   /* 
    * Compile and apply the filter
    */
    pcap_lookupnet(device, &net, &mask, errbuf);
    if(pcap_compile(handle, &filter, "ip", 0, mask)<0)
    {
	fprintf(stderr, "pcap_compile(): %s\n", pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }
    pcap_setfilter(handle, &filter);


    /*
     * Handle options
     */
    src_ip  = 0;
    dst_ip  = 0;
    src_prt = 0;
    dst_prt = 0;
    payload = NULL;
    payload_s = 0;
    while((c = getopt(argc, argv, "d:s:p:")) != EOF)
    {      
        switch (c)
        {
            /*
             *  We expect the input to be of the form `ip.ip.ip.ip.port`.  We
             *  point cp to the last dot of the IP address/port string and
             *  then seperate them with a NULL byte.  The optarg now points to
             *  just the IP address, and cp points to the port.
             */
            case 'd':
                if (!(cp = strrchr(optarg, '.')))
                {
                    usage(argv[0]);
                }
                *cp++ = 0;
                dst_prt = (u_short)atoi(cp);
                if ((dst_ip = libnet_name2addr4(l, (u_char*)optarg, LIBNET_RESOLVE)) == -1)
                {
                    fprintf(stderr, "Bad destination IP address: %s\n", optarg);
                    exit(EXIT_FAILURE);
                }
                break;
                break;
            case 'p':
                payload = (u_char*)optarg;
                payload_s = strlen((char*)payload);
                break;
            case 's':
                if (!(cp = strrchr(optarg, '.')))
                {
                    usage(argv[0]);
                }
                *cp++ = 0;
                src_prt = (u_short)atoi(cp);
                if ((src_ip = libnet_name2addr4(l, (u_char*)optarg, LIBNET_RESOLVE)) == -1)
                {
                    fprintf(stderr, "Bad source IP address: %s\n", optarg);
                    exit(EXIT_FAILURE);
                }
                break;
        }
    }
    if (!src_ip || !src_prt || !dst_ip || !dst_prt)
    {
        usage(argv[0]);
        exit(EXIT_FAILURE);
    }

    tcp = libnet_build_tcp(
        src_prt,                                    /* source port */
        dst_prt,                                    /* destination port */
        0x01010101,                                 /* sequence number */
        0x00,                                       /* acknowledgement num */
        TH_SYN,                                     /* control flags */
        32767,                                      /* window size */
        0,                                          /* checksum */
        0,                                          /* urgent pointer */
        LIBNET_TCP_H + payload_s,                   /* TCP packet size */
        payload,                                    /* payload */
        payload_s,                                  /* payload size */
        l,                                          /* libnet handle */
        0);                                         /* libnet id */
    if (tcp == -1)
    {
        fprintf(stderr, "Can't build TCP SYN header: %s\n", libnet_geterror(l));
        goto bad;
    }

    ip = libnet_build_ipv4(
        LIBNET_IPV4_H + LIBNET_TCP_H + payload_s,   /* length */
        0,                                          /* TOS */
        242,                                        /* IP ID */
        0,                                          /* IP Frag */
        64,                                         /* TTL */
        IPPROTO_TCP,                                /* protocol */
        0,                                          /* checksum */
        src_ip,                                     /* source IP */
        dst_ip,                                     /* destination IP */
        NULL,                                       /* payload */
        0,                                          /* payload size */
        l,                                          /* libnet handle */
        0);                                         /* libnet id */
    if (ip == -1)
    {
        fprintf(stderr, "Can't build IP header: %s\n", libnet_geterror(l));
        goto bad;
    } 

    /*
     *  Write it to the wire.
     */
    c = libnet_write(l);
    if (c == -1)
    {
        fprintf(stderr, "Write error: %s\n", libnet_geterror(l));
        goto bad;
    }
    else
    {
        fprintf(stderr, "Wrote %d byte TCP packet; check the wire.\n", c);
    }

    /* 
     * Answering machine part 
     */
    printf("waiting for my answer ...\n");
    while(keep_waiting)
    {
	if((packet = pcap_next(handle, &header)))
	{
	    printf("capture: %u %u\n", header.caplen, header.len);

	    answer = libnet_answer(l, packet, header.caplen, 
				   LIBNET_OUTPUT_IS_FIRST, &last);

	    switch (answer) 
	    {
		case -1: /* error */
		    fprintf(stderr,"error: [%s]\n", libnet_geterror(l));
		    if (last == LIBNET_PBLOCK_IPV4_H)
		    {
			printf("Error but found a valid answer until IP layer\n");
			keep_waiting = 0;
		    }
		    else
		    {
			goto bad;
		    }
		    break;
		case 0 : /* not the expected answer */
		    fprintf(stderr,"bad answer (last=0x%x)\n", last);
                    /*
		      if (last == LIBNET_PBLOCK_IPV4_H)
		      {
		      printf("Not an answer but found a valid answer until IP layer:\n");
		      dump(packet, header.caplen);
		      keep_waiting = 0;
		      }
		    */

		    break;
		default:
		    printf("Got an answer:\n");
		    dump(packet, header.caplen);
		    keep_waiting = 0;
	    }
	}
    }

    /* 
     * Let's send he last ACK now 
     */
    synack = (struct libnet_tcp_hdr*)(packet + 
				      sizeof(struct libnet_ethernet_hdr) +
				      sizeof(struct libnet_ipv4_hdr));

    printf("TCP ports  %hu->%hu\n", ntohs(synack->th_sport), ntohs(synack->th_dport));
    printf("TCP numbers  0x%x (%u) 0x%x (%u)\n", 
	   ntohl(synack->th_seq), ntohl(synack->th_seq),
	   ntohl(synack->th_ack), ntohl(synack->th_ack));

    /* 
     * check if remote port was open before sending the last ACK
     */
    if (synack->th_flags & TH_SYN)
    {
	tcp = libnet_build_tcp(
	    src_prt,                              /* source port */
	    dst_prt,                              /* destination port */
	    ntohl(synack->th_ack),                /* sequence number */
	    ntohl(synack->th_seq)+1,              /* acknowledgement num */
	    TH_ACK,                               /* control flags */
	    32767,                                /* window size */
	    0,                                    /* checksum */
	    0,                                    /* urgent pointer */
	    LIBNET_TCP_H + payload_s,             /* TCP packet size */
	    payload,                              /* payload */
	    payload_s,                            /* payload size */
	    l,                                    /* libnet handle */
	    tcp);                                 /* libnet id */
	if (tcp == -1)
	{
	    fprintf(stderr, "Can't build TCP SYN|ACK header: %s\n", libnet_geterror(l));
	    goto bad;
	}
	
	/*
	 *  Write it to the wire.
	 */
	c = libnet_write(l);
	if (c == -1)
	{
	    fprintf(stderr, "Write error: %s\n", libnet_geterror(l));
	    goto bad;
	}
	else
	{
	    fprintf(stderr, "Wrote %d byte TCP packet; check the wire.\n", c);
	}
    }
    else
    {
	printf("Sorry, can't send last ACK as remote port is not open\n");
    }

    libnet_destroy(l);
    return (EXIT_SUCCESS);
bad:
    libnet_destroy(l);
    return (EXIT_FAILURE); 
}


void
usage(char *name)
{
    fprintf(stderr,
        "usage: %s device -s source_ip.source_port -d destination_ip.destination_port"
        " [-p payload]\n",
        name);
}

/* EOF */


Bei einem eigenem Protokoll, was du möglicherweise gar nicht brauchst,
würde ich mir das nächste halbe Jahr frei nehmen 😉
Je nach tiefe müsstest du da genaue Kernelparameter wissen und
unter Windows ohne Sourcecode stelle ich mir das jetzt sehr knifflig vor...
ansonsten definiere mal genauer was du coden magst.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo zusammen,

Protokoll kann man ja auf unterschiedlichen Ebenen (des ISO-Schichtenmodells) verstehen. Mir ist gar nicht genau klar, welche Ebene gemeint ist. Wenn es sowas auf der Ebene http/ftp o.ä. gemeint ist, dürfte es nicht allzu schwierig werden. Syntax für Kommandos und Parameter definieren und als String hin- und herschicken.

herbivore

Fabian Themenstarter:in
1.985 Beiträge seit 2004
vor 18 Jahren

Hallo ihr beiden,

danke schon mal für die Infos. Es geht mir mehr in die Richtung von Programmierhans. Ich möchte über TCP beliebige Daten zwischen zwei Applikationen austauschen. Dazu verwende ich die TCP-Klassen von C#.
Dabei geht es mir darum, sicherzustellen, was ich so als "Handshake" austauschen muss / sollte, damit ich keine Probleme bekomme.

Gruß,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

Fabian Themenstarter:in
1.985 Beiträge seit 2004
vor 18 Jahren

Original von herbivore
Hallo zusammen,

Protokoll kann man ja auf unterschiedlichen Ebenen (des ISO-Schichtenmodells) verstehen. Mir ist gar nicht genau klar, welche Ebene gemeint ist. Wenn es sowas auf der Ebene http/ftp o.ä. gemeint ist, dürfte es nicht allzu schwierig werden. Syntax für Kommandos und Parameter definieren und als String hin- und herschicken.

herbivore

*Boom*, Volltreffer 🙂. Nur gerne mit den TCP-Klassen von C#. FTP ist auch eine Alternative. Wenn, würde ich gerne mit TCP das "Handshake" aushandeln, also im Falle eines Updaters überprüfen, welche Version ist denn da am anderen Ende und was braucht die für die neue Version und dann die eigentlichen Daten über FTP verschicken.

Kann man so ein Aushandeln auch mit FTP machen?

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

I
72 Beiträge seit 2005
vor 18 Jahren

FTP sitzt "über" TCP, also wenn du eine FTP Anwendung schreibts,
hast du als untergeordneten Layer immer TCP (gibt Ausnahmen, aber
nicht für was du willst).

FTP ist sozusagen die "Anwendungsebene", ablaufen tut das alles
auch über TCP/IP... sieh FTP als "interface" um Daten über TCP/IP zu übertragen.

Das zum Thema aushandeln, mit den C# klasses dafür kann ich dir nicht
helfen sry, aber lies die mal die RFC's über grundlegende Netzwerkarchitektur
von TCP, IP, FTP durch, da steht eigentlich auch alles drin was du wissen
möchtest (zumindest die Theorie des Ganzen).

Fabian Themenstarter:in
1.985 Beiträge seit 2004
vor 18 Jahren

Hallo,

danke Euch allen. Das hilft mir schon mal weiter.

Jetzt habe ich aber noch zwei weitere Frage:

Wenn ich über die TCP-Klassen Daten sende, dann reagiert meine GUI in der Zeit nicht mehr. Wie kann ich das Problem umgehen? Muss ich das ganze in eine weiteren Thread auslagern oder geht das auch anders?

Zweite Frage bezieht sich auf die Art, wie ich Daten sende. Ich Prinzip habe ich vor, jegliche Art von Daten zu verschicken (Binär-, txt-Dateien etc.). Muss ich die vorher auf eine bestimmte Art und Weise aufbereiten oder "einfache" senden?

Und eine dritte Frage habe ich doch noch 🙂. Hat jemand Buchempfehlungen oder sonstige Informationen über die TCP- und FTP-Klasse in CSharp und die Verwendung der beiden? Also mal die Hilfe und MSDN ausgenommen.

Ich danke Euch,
Gruß Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

1.549 Beiträge seit 2004
vor 18 Jahren

Was das einfrieren betrifft da hilft wirklich einfach ein eigener Tread weiter

Wir Arbeiten eigendlich nicht wir nehmen nur das geld

M
329 Beiträge seit 2004
vor 18 Jahren

Schau dir mal die Links "Netzwerkprogrammierung mit C#" Teil 1-6 an, hat mir unglaublich geholfen
Hier der Link

Fabian Themenstarter:in
1.985 Beiträge seit 2004
vor 18 Jahren

Original von michaelschuler
Schau dir mal die Links "Netzwerkprogrammierung mit C#" Teil 1-6 an, hat mir unglaublich geholfen

>

Hey thx. Habs mal überflogen und sieht richtig gut aus. Thx schonmal.

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

Fabian Themenstarter:in
1.985 Beiträge seit 2004
vor 18 Jahren

Original von michaelschuler
Schau dir mal die Links "Netzwerkprogrammierung mit C#" Teil 1-6 an, hat mir unglaublich geholfen

>

Hallo michaelschuler,

jetzt noch mal ein dickes Danke! Die 6 Teile sind sowas von anschaulich und gut erklärt, ich hatte da eine Menge von.

Habe aber noch eine Frage an Dich: Wie ich Deinem Post entnehmen kann, hast Du auch schon mal was mit Netzwerkprogammierung gemacht oder 🙂?

Ich würde gerne eine Anzeige realisieren, wie viel Bytes schon übertragen wurden, um sowas später zum Beispiel grafisch darstellen zu können. Kannst Du mir sagen, wie ich am besten abfragen / speichern kann, wie viel denn schon übertragen wurde?

Gruß und Danke,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

F
529 Beiträge seit 2003
vor 18 Jahren

Du kannst dazu eine neue Klasse erzeugen, die von der Socket oder Streamklasse erbt. Dann musst du nur noch die Methoden zum Lesen und Schreiben überschreiben und die übertragenen Bytes mitzählen. Dann weißt du genau, wie viel du übertragen hast. Oder du summierst auf eine Int64-Variable auf, wie viele Bytes du gesendet hast. Weiterhin kann du ja noch in einer Zweiten Variablen speichern, wie viele Bytes empfangen wurden.

Übrigens rate ich von dem Tutorial ab, da alle Beispiele synkron sind. Mache lieber das ganze mit AsyncCallbacks (hier).

Wenn das ganze mit Threads auf Packete wartet hat man zwar den Vorteil, dass der Quelltext leichter Verständlich ist, und man nicht so viel Programmieraufwand hat, aber wenn man das ganze mit AsyncCallbacks macht, muss man sich nicht um die Timeouts von Clients kümmern. Wenn dann nämlich jemand bei Threads die Gegenseite per Taskmanager von Windows beendet, bekommt der Socket das nicht mit und es kann passieren, dass der Thread ewig auf Daten wartet wenn man sich nicht um sein Ableben kümmert(Ich kenne das nur zu Gut! Es ging einmal sogar so weit, dass das Programm sich selbst per Process.Kill() beenden musste, weil in irgent einer Lib, auf die ich keinen Zugriff hatte, ein Thread nicht beenden wollte, wenn das Programm beendet wurde und vorher die Gegenseite sich nicht abgemeldet hat. Den Fehler zu suchen war nicht lustig. Ich habe ihn dann nach einer ewigen Zeitspanne durch Zufall entdeckt!). Wenn man aber statt dessen die AsyncCallbacks verwendet, dann kann man sich Sicher sein, dass nach der Zeit x eine SocketException fliegt. Daher würde ich auf alle Fälle die asyncr. Verbindungen bevorzugen.

Besuchen sie das VisualC++ - Forum

Fabian Themenstarter:in
1.985 Beiträge seit 2004
vor 18 Jahren

Original von Franknstein
Du kannst dazu eine neue Klasse erzeugen, die von der Socket oder Streamklasse erbt. Dann musst du nur noch die Methoden zum Lesen und Schreiben überschreiben und die übertragenen Bytes mitzählen. Dann weißt du genau, wie viel du übertragen hast. Oder du summierst auf eine Int64-Variable auf, wie viele Bytes du gesendet hast. Weiterhin kann du ja noch in einer Zweiten Variablen speichern, wie viele Bytes empfangen wurden.

Na klar! Da hätte ich auch selber drauf kommen können. Habs auch grad ausprobiert und es funktioniert ohne Probleme.

Original von Franknstein
Übrigens rate ich von dem Tutorial ab, da alle Beispiele synkron sind. Mache lieber das ganze mit AsyncCallbacks (
>
).

Wenn das ganze mit Threads auf Packete wartet hat man zwar den Vorteil, dass der Quelltext leichter Verständlich ist, und man nicht so viel Programmieraufwand hat, aber wenn man das ganze mit AsyncCallbacks macht, muss man sich nicht um die Timeouts von Clients kümmern. Wenn dann nämlich jemand bei Threads die Gegenseite per Taskmanager von Windows beendet, bekommt der Socket das nicht mit und es kann passieren, dass der Thread ewig auf Daten wartet wenn man sich nicht um sein Ableben kümmert(Ich kenne das nur zu Gut! Es ging einmal sogar so weit, dass das Programm sich selbst per Process.Kill() beenden musste, weil in irgent einer Lib, auf die ich keinen Zugriff hatte, ein Thread nicht beenden wollte, wenn das Programm beendet wurde und vorher die Gegenseite sich nicht abgemeldet hat. Den Fehler zu suchen war nicht lustig. Ich habe ihn dann nach einer ewigen Zeitspanne durch Zufall entdeckt!). Wenn man aber statt dessen die AsyncCallbacks verwendet, dann kann man sich Sicher sein, dass nach der Zeit x eine SocketException fliegt. Daher würde ich auf alle Fälle die asyncr. Verbindungen bevorzugen.

Hmm. Dein Einwand klingt logisch (soweit ich das schon beurteilen kann 🙂).

Hast Du evtl. noch ein paar Links oder Buchempfehlungen zu dem Thema? Vielleicht auch auf Deutsch? Hab zwar kein größeres Problem mit Englischen Texten, aber auf Deutsch ist es trotzdem etwas leichter und einfacher verständlich.

Deswegen habe ich auch diesen Thread eröffnet, um auf solche Dinge hingewiesen zu werden, da das Thema für mich doch ziemlich neu ist.

Danke und Gruß,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

Fabian Themenstarter:in
1.985 Beiträge seit 2004
vor 18 Jahren

Hallo,

ich muss leider doch noch ein Post machen 😦. Das mit der Versenden von Kommandos etc. funktioniert jetzt auch mit der Asynchronen Methode ohne Probleme.

Mein Problem liegt jetzt darin, Dateien zu versenden. Mal sind die Dateien zu klein (es fehlt z.b. 1 KB), mal sind sie zu groß (5KB zu viel). Kann mir jemand noch Infos dazu geben, wie ich Dateien über so einen Stream verschicken kann? Irgendwo habe ich noch einen dummen Fehler, finde den nicht und verzweifle schon fast daran 😦.

Danke und Gruß,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de