"Illegal seek" Fehler beim arbeiten mit socket-streams mit nicht-leerem Puffer Lesen

Schreibe ich momentan eine server-Anwendung auf Linux x86_64 mit <sys/socket.h>.
Nach der Annahme einer Verbindung über accept() verwende ich fdopen() wickeln abgerufen Buchse in eine FILE* stream.

Schreiben in und Lesen aus, dass FILE* stream in der Regel ganz gut funktioniert, aber die Buchse wird unsusable sobald ich schreiben, es hat einen nicht-leeren Puffer Lesen.

Zur demonstration, die ich geschrieben habe, einige code, der wartet auf eine Verbindung, dann liest die Eingabe zeilenweise in einen Puffer Lesen mit fgetc(). Wenn die Zeile zu lang und passt nicht in den Puffer, ist es nicht ganz Lesen, sondern Lesen Sie während der nächsten iteration.

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

FILE* listen_on_port(unsigned short port) {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in name;
        name.sin_family = AF_INET;
        name.sin_port = htons(port);
        name.sin_addr.s_addr = htonl(INADDR_ANY);
        if(bind(sock, (struct sockaddr*) &name, sizeof(name)) < 0)
                perror("bind failed");
        listen(sock, 5);
        int newsock = accept(sock, 0, 0);
        return fdopen(newsock, "r+");
}

int main(int argc, char** argv) {
        int bufsize = 8;
        char buf[9];
        buf[8] = 0; //ensure null termination

        int data;
        int size;

        //listen on the port specified in argv[1]
        FILE* sock = listen_on_port(atoi(argv[1]));
        puts("New connection incoming");

        while(1) {
                //read a single line
                for(size = 0; size < bufsize; size++) {
                        data = fgetc(sock);
                        if(data == EOF)
                                break;
                        if(data == '\n') {
                                buf[size] = 0;
                                break;
                        }
                        buf[size] = (char) data;
                }

                //check if the read failed due to an EOF
                if(data == EOF) {
                        perror("EOF: Connection reset by peer");
                        break;
                } else {
                        printf("Input line: '%s'\n", buf);
                }

                //try to write ack
                if(fputs("ack\n", sock) == EOF)
                        perror("sending 'ack' failed"); 

                //try to flush
                if(fflush(sock) == EOF)
                        perror("fflush failed");        
        }

        puts("Connection closed");
}

Sollte der code kompilieren des gcc ohne Besondere Parameter. Führen Sie es mit der port-Nummer als argument und netcat verwenden, um eine Verbindung herzustellen lokal.

Nun, wenn Sie versuchen, senden von strings, die kürzer sind als 8 Zeichen, diese laufen einwandfrei.
Aber wenn Sie senden Sie eine Zeichenfolge mit mehr als 10 Zeichen, wird das Programm scheitern.
Dieses Beispiel für die Eingabe:

ab
cd
abcdefghij

Erstellen dieser Ausgabe:

New connection incoming
Input line: 'ab'
Input line: 'cd'
Input line: 'abcdefgh'
fflush failed: Illegal seek
EOF: Connection reset by peer: Illegal seek
Connection closed

Wie Sie sehen, (zu Recht) nur die ersten 8 Zeichen abcdefgh gelesen, aber wenn das Programm versucht zu senden, die 'ack' - saite (die der client nie receves), und dann Spülen Sie die Ausgabe-Puffer, so erhalten wir eine Illegal seek Fehler, und beim nächsten Aufruf fgetc() wird EOF zurückgegeben.

Wenn die fflush() Teil auskommentiert ist, immer der selbe Fehler Auftritt, aber der

fflush failed: Illegal seek

Linie fehlt von der server-Ausgabe.

Wenn die fputs(ack) Teil auskommentiert ist, alles scheint zu funktionieren wie beabsichtigt, aber eine perror() manuell aufgerufen gdb noch Berichte eine "Illegal seek" Fehler.

Wenn beide fputs(ack) und fflush() sind auskommentiert, alles hat so funktionieren wie Sie sollen.

Leider habe ich nicht in der Lage zu finden, eine gute Dokumentation, noch irgendwelchen Internet-Diskussionen über dieses problem, so Ihre Hilfe wäre sehr geschätzt werden.

Bearbeiten

Die Lösung, die ich schließlich entschied sich für ist zu nicht Verwendung fdopen() und FILE*, da scheint es keine "saubere" Möglichkeit der Umwandlung von a-Buchse fd in einen FILE* zuverlässig eingesetzt r+ - Modus.
Stattdessen habe ich direkt gearbeitet, die auf der socket fd, Schreibe meine eigenen Ersatz-code für fputs und fprintf.

Wenn jemand braucht es, hier ist der code.

InformationsquelleAutor mic_e | 2012-04-21

Schreibe einen Kommentar