ubuntuusers.de

Zeitüberwachung/Timeout bei einfacher Netzwerkprogrammierung (C)

Status: Ungelöst | Ubuntu-Version: Ubuntu MATE 20.04 (Focal Fossa)
Antworten |

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6450

Wohnort: Hamburg

Ich experimentiere immer noch mit Netzwerkprogrammierung (ist spannend). Dabei habe ich festgestellt, dass ich zumindest auf der Clientseite eine Zeitüberwachung benötige. So wie ich das brauche, wird das in meinen Büchern nicht erwähnt.

Um auch längere Texte (text/plain), die sich über mehrere Sendeblöcke erstrecken können, habe ich die read_line.c verwendet. Damit ist zumindest das Abarbeiten der HTTP-Header recht einfach. Eingebaut habe ich das in folgendem Programmabschnitt (Problemstelle mit <<<< markiert):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
int
send_request( char * sbuf ) {
    int     sock_fd;
    FILE *  fp;
    char *  buffer = malloc( BUF );
    struct  sockaddr_in address;
    int     n;
    char *  cp = NULL;
    int     content_length;
    int     file_type;

    if( (sock_fd = socket( AF_INET, SOCK_STREAM, 0 )) > 0 )
        printf( "Socket wurde angelegt\n" );
    address.sin_family = AF_INET;
    address.sin_port = htons( server_port );
    inet_aton( serveraddr, &address.sin_addr );
    if( connect( sock_fd, (struct sockaddr*)&address, sizeof( address ) ) == 0 ) {
        printf( "Verbindung mit dem Server (%s) hergestellt\n", inet_ntoa( address.sin_addr ) );
    } else {
        printf( "Keine Verbindung\n" );
        close( sock_fd );
        return -1;
    }
    send( sock_fd, sbuf, strlen( sbuf ), 0 );
    content_length = 0;
    file_type = 0;
    while( 1 ) {
        n = readLine( sock_fd, buffer, BUF );
        if( n < 0 ) {
            printf( "Read error!\n" );
            return -1;
        }
        if( n == 0 ) {
            printf( "empty\n" );
            break;
        }
        cp = buffer;
        if(  *cp == '\r' && *(cp+1) == '\n')
            break;
        printf( "> %s", buffer );
        if( strncmp( buffer, "Content-Length: ", 16 ) == 0 ) {
            cp += 16;
            content_length = atoi( cp );
            continue;
        }
        if( strncmp( buffer, "Content-Type: image/png", 23 ) == 0 ) {
            file_type = 1;
            continue;
        }
        if( strncmp( buffer, "Content-Type: text/plain", 24 ) == 0 ) {
            file_type = 2;
            continue;
        }
    }
    if( file_type == 1  &&  content_length > 0 ) {
        if( (fp = fopen( "tmpthumb.png", "wb" )) ) {
            while( content_length > 0 ) {
                n = recv( sock_fd, buffer, BUF, 0 );
                if( n > 0 ) {
                    fwrite( buffer, n, 1, fp );
                    content_length -= n;
                } else {
                    break;
                }
            }
            fclose( fp );
        }
    }
    if( file_type == 2  &&  content_length > 0 ) {
        while( content_length > 0 ) {
            n = readLine( sock_fd, buffer, BUF ); // <<<<
            if( n < 0 ) {
                printf( "Read error!\n" );
                return -1;
            }
            if( n == 0 ) {
                break;
            }
            printf( "%s", buffer );
            content_length -= n;
        }
    }
    close( sock_fd );
    return 0;
}

Das Problem entsteht nun, wenn der Server abstürzt, beendet wird oder eine falsche Länge angegeben hat. In meinem Fall war die Länge sogar richtig, aber es wurde ein zusätzliches Nullbyte angehängt. Daraufhin wartet die verlinkte Fremdfunktion bis in alle Ewigkeit auf die Sequenz "\r\n", die aber nicht mehr kommt.

Wie kann ich aus der Nummer raus kommen? Meine erste Idee war ein Timer. Aber was sollte der auslösen? Es ist ja alles der selbe Prozess. Der soll sich ja nicht komplett selbst abwürgen.

Antworten |