Frage

Ich bin ein bisschen verwirrt über socket-Programmierung in C.

Erstellen Sie eine Steckdose, binden Sie es an eine Schnittstelle und eine IP-Adresse und bekommen es zu hören.Ich fand ein paar von web-Ressourcen und verstanden es gut.Insbesondere fand ich einen Artikel Netzwerk-Programmierung unter Unix-Systemen sehr informativ.

Was mich verwirrt, ist das timing von Daten der Ankunft auf dem sockel.

Wie können Sie sagen, wenn Pakete ankommen, und wie groß das Paket ist, müssen Sie alles tun, die schweres heben sich?

Meine grundlegende Annahme ist hier, dass Pakete variabler Länge sein können, so, wenn binäre Daten beginnt, die unten die Steckdose, wie Sie beginnen zu konstruieren, die Pakete aus, die?

War es hilfreich?

Lösung

Die kurze Antwort ist, dass Sie alles tun, die schweres heben sich.Sie können benachrichtigt werden, dass es Daten zu Lesen, aber Sie nicht wissen, wie viele bytes zur Verfügung stehen.In den meisten IP-Protokolle verwenden, variable-Länge Pakete, es wird ein header mit einem bekannten Feste Länge vorangestellt, um das Paket.Dieser header enthält die Länge des Pakets.Sie Lesen die überschrift, um die Länge des Paket, dann Lesen Sie die Paket.Sie wiederholen dieses Muster (Lesen header, dann Lesen Sie Paket), bis die Kommunikation abgeschlossen ist.

Beim Lesen von Daten von einem socket, die Sie anfordern, eine bestimmte Anzahl von bytes.Die read-Aufruf blockiert, bis die angeforderte Anzahl von bytes, die gelesen werden, aber es kann zurück weniger bytes als das, was angefordert wurde.Wenn dies passiert, einfach erneut zu Lesen, und beantragen die verbleibenden bytes.

Hier ist eine typische C-Funktion für das Lesen einer bestimmten Anzahl von bytes von einem socket:

/* buffer points to memory block that is bigger than the number of bytes to be read */
/* socket is open socket that is connected to a sender */
/* bytesToRead is the number of bytes expected from the sender */
/* bytesRead is a pointer to a integer variable that will hold the number of bytes */
/*           actually received from the sender. */
/* The function returns either the number of bytes read, */
/*                             0 if the socket was closed by the sender, and */
/*                            -1 if an error occurred while reading from the socket */
int readBytes(int socket, char *buffer, int bytesToRead, int *bytesRead)
{
    *bytesRead = 0;
    while(*bytesRead < bytesToRead)
    {
        int ret = read(socket, buffer + *bytesRead, bytesToRead - *bytesRead);
        if(ret <= 0)
        {
           /* either connection was closed or an error occurred */
           return ret;
        }
        else
        {
           *bytesRead += ret;
        }
    }
    return *bytesRead;
}

Andere Tipps

Also, die Antwort auf Ihre Frage hängt ein gutes Stück auf, ob Sie über UDP oder TCP als Ihre transport.

Für UDP, wird das Leben viel einfacher, dass Sie können Anruf recv/recvfrom/recvmsg mit der Paket Größe, die Sie benötigen (Sie würden wahrscheinlich senden Pakete fester Länge von der Quelle sowieso), und machen die Annahme, dass, wenn Daten verfügbar sind, ist es dort in vielfachen von Paket-Länge Größen.(I. E.Sie rufen recv* mit der Größe der E-side-Paket, und Sie sind gesetzt.)

Für TCP -, wird das Leben ein wenig interessanter - für die Zwecke dieser Erklärung ist, gehe ich davon aus, dass Sie bereits wissen, wie socket(), bind(), listen() und accept() - wobei letztere, wie man die file-descriptor (FD) Ihres neu gemacht-Verbindung.

Es gibt zwei Möglichkeiten, die I/O für a-Buchse - zu blockieren, in denen du call read(fd, buf, N) und Lesen Sie sitzt da und wartet, bis Sie Sie gelesen haben N-bytes in buf - oder non-blocking, in dem Sie haben zu prüfen (mittels select() oder poll ()), ob die FD lesbar ist, und DANN machen Sie Ihre read().

Beim Umgang mit TCP-basierte verbindungen, die OS nicht zahlen Aufmerksamkeit auf die Paket Größe ist, da Sie es als einen kontinuierlichen Strom von Daten, der nicht seperate packet-sized chunks.

Wenn die Anwendung verwendet die "Pakete" (verpackt oder unverpackt Datenstrukturen, Sie sind vorbei), Sie sollten in der Lage sein zu rufen, Lesen() mit dem richtigen argument Größe, und Lesen Sie eine komplette Datenstruktur aus der Steckdose auf eine Zeit.Die einzige Einschränkung, die Sie zu tun haben, ist daran zu erinnern, richtig zu byte-Reihenfolge die Daten, die Sie versenden, im Falle der Quell-und Zielsystem unterschiedliche byte-endian-ness.Dies gilt sowohl für UDP und TCP.

Soweit die *NIX-socket-Programmierung betroffen ist, empfehle ich dringend, W.Richard Stevens Unix Network Programming, Vol.1" (UNPv1) und "Erweiterte Programmierung in der Unix-Umgebung" (APUE).Der erste ist ein Wälzer über Netzwerk-basierte Programmierung, unabhängig von der transport-und der letztere ist ein guter Allround-Programmierung-Buch, wie es gilt für *NIX-basierte Programmierung.Suchen Sie auch nach "TCP/IP Illustrated", Volumes 1 und 2.

Wenn Sie eine Lesen in der Buchse, Sie sagen, wie viele maximal bytes zu Lesen, aber wenn es nicht, dass viele, es gibt Sie jedoch viele er hat.Es ist bis zu Sie zu design das Protokoll, damit Sie wissen, ob Sie haben eine partielle Paket oder nicht.Zum Beispiel in der Vergangenheit beim senden von Variablen Länge der Binärdaten, ich würde einen int-am Anfang gesagt, wie viele bytes zu erwarten.Ich würde tun, eine lese-Anforderung einer Anzahl von bytes, die größer als die größte mögliche Paket in meinem Protokoll, und dann würde ich vergleichen das erste int gegen wie viele bytes ich erhalten hatte, und entweder verarbeiten oder zu versuchen mehr liest, bis ich Sie bekommen hatte das komplette Paket, abhängig.

Steckdosen funktionieren auf einem höheren Niveau als raw-Pakete - es ist wie ein Datei können Sie Lesen/schreiben aus.Auch, wenn Sie versuchen, zu Lesen von einem socket, das Betriebssystem blockiert wird (auf Eis gelegt), die Ihren Prozess, bis es Daten, die Anforderung zu erfüllen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top