C-Programm mit fork() und while(1)

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • C-Programm mit fork() und while(1)

    Hallo an Alle,

    ich würde mich sehr über einen Tip in folgender Sache freuen:

    Habe ein kleines C-Programm unter Linux, dass einmal Kindprozesse mit fork() erzeugen soll und dass sich nicht beenden soll und bereit sein für weitere Anfragen. Das ständige bereit sein habe ich mit while(1) gelöst. Scheinbar darf fork nicht in der while(1) Schleife stehen. Nur wie könnte man das sonst lösen?

    Vielen Dank für einen Tip.

    Viele Grüße

    Walter

    Code:


    /*****************************************************************/
    /* Dateiname : ServerDateiSenden.c */
    /* Beschreibung: Server-Programm */
    /* Analysiert einen HTTP-GET-Befehl und versucht */
    /* die angeforderte Datei zu senden */
    /*****************************************************************/

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>

    int main()
    {
    int server_socket, client_socket;
    int anzahl, laenge, childpid;
    struct sockaddr_in serverinfo, clientinfo;
    char zeichen;
    char empfangen[1000];
    char *position1, *position2;
    char dateiname[100];
    char text_http_ok[] = "HTTP/1.0 200 OK\r\n\r\n";
    char text_html_anfang[] = "<HTML><BODY>";
    char text_html_ende[] = "</BODY></HTML>";
    FILE *datei;

    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    serverinfo.sin_family = AF_INET;
    serverinfo.sin_addr.s_addr = htonl(INADDR_ANY);
    serverinfo.sin_port = htons(5000);
    laenge = sizeof(serverinfo);

    bind(server_socket, (struct sockaddr *)&serverinfo, laenge);
    listen(server_socket, 3);

    while (1)
    {
    printf("\n Der Server wartet...");
    fflush(stdout);

    client_socket = accept(server_socket, (struct sockaddr *)&clientinfo, &laenge);

    printf("\n Verbindung mit %s",inet_ntoa(clientinfo.sin_addr));
    childpid = fork();
    if (childpid ==0)
    {
    close(server_socket);
    }



    anzahl = read(client_socket,empfangen,sizeof(empfangen));
    empfangen[anzahl]=0;
    write(client_socket,text_http_ok,strlen(text_http_ok));

    if (position1 = strstr(empfangen,"GET"))
    {
    if (position2 = strstr(empfangen,"HTTP"))
    {
    laenge = position2 - position1 - 6;
    strncpy(dateiname,position1+5,laenge);
    dateiname[laenge]=0;
    printf("\n GET Befehl für Datei %s gefunden",dateiname);
    datei = fopen(dateiname,"rt");
    if (datei==NULL)
    {
    printf("\n Datei existiert nicht");
    write(client_socket,text_html_anfang,strlen(text_html_anfang));
    write(client_socket,"<br>Datei existiert nicht",25);
    write(client_socket,text_html_ende,strlen(text_html_ende));
    }
    else
    {
    printf("\n Sende Datei %s",dateiname);

    do
    {
    zeichen = fgetc(datei);
    if (!feof(datei))
    {
    write(client_socket,&zeichen,1);
    }
    } while (!feof(datei));

    fclose(datei);
    }
    }
    else
    {
    printf("\n Der HTTP-Parser hat keinen HTTP-Befehl gefunden");
    write(client_socket,text_html_anfang,strlen(text_html_anfang));
    write(client_socket,"kein HTTP-Befehl gefunden",25);
    write(client_socket,text_html_ende,strlen(text_html_ende));
    }
    }
    else
    {
    printf("\n Der HTTP-Parser hat keinen GET-Befehl gefunden");
    write(client_socket,text_html_anfang,strlen(text_html_anfang));
    write(client_socket,"kein GET-Befehl gefunden",24);
    write(client_socket,text_html_ende,strlen(text_html_ende));
    }
    printf("\n");
    close(client_socket);
    }
    }
    }
  • Kommt eine Fehlermeldung oder warum glaubst du, dass fork() nicht innerhalb der while-Schleife vorkommen darf?
    Ich konnte deinen Code bei mir problemlos kompilieren und ausführen (ohne etwas über den Port zu empfangen).
    Nur das letzte } ist zu viel und ich würde (als Tipp) noch unistd.h einbinden, sonst fehlen dem Compiler die Signaturen für read(), fork(), etc. (mit gcc -Wall einsehbar).
    Beim nächsten Mal bitte Code-Tags verwenden, damit die Einrückungen erhalten bleiben.
    Hier nochmals sauber formatiert:

    Quellcode

    1. /*****************************************************************/
    2. /* Dateiname : ServerDateiSenden.c */
    3. /* Beschreibung: Server-Programm */
    4. /* Analysiert einen HTTP-GET-Befehl und versucht */
    5. /* die angeforderte Datei zu senden */
    6. /*****************************************************************/
    7. #include <sys/types.h>
    8. #include <sys/socket.h>
    9. #include <unistd.h>
    10. #include <stdio.h>
    11. #include <netinet/in.h>
    12. #include <arpa/inet.h>
    13. #include <string.h>
    14. int main()
    15. {
    16. int server_socket, client_socket;
    17. int anzahl, laenge, childpid;
    18. struct sockaddr_in serverinfo, clientinfo;
    19. char zeichen;
    20. char empfangen[1000];
    21. char *position1, *position2;
    22. char dateiname[100];
    23. char text_http_ok[] = "HTTP/1.0 200 OK\r\n\r\n";
    24. char text_html_anfang[] = "<HTML><BODY>";
    25. char text_html_ende[] = "</BODY></HTML>";
    26. FILE *datei;
    27. server_socket = socket(AF_INET, SOCK_STREAM, 0);
    28. serverinfo.sin_family = AF_INET;
    29. serverinfo.sin_addr.s_addr = htonl(INADDR_ANY);
    30. serverinfo.sin_port = htons(5000);
    31. laenge = sizeof(serverinfo);
    32. bind(server_socket, (struct sockaddr *)&serverinfo, laenge);
    33. listen(server_socket, 3);
    34. while (1)
    35. {
    36. printf("\n Der Server wartet...");
    37. fflush(stdout);
    38. client_socket = accept(server_socket, (struct sockaddr *)&clientinfo, &laenge);
    39. printf("\n Verbindung mit %s",inet_ntoa(clientinfo.sin_addr));
    40. childpid = fork();
    41. if (childpid ==0)
    42. {
    43. close(server_socket);
    44. }
    45. anzahl = read(client_socket,empfangen,sizeof(empfangen));
    46. empfangen[anzahl]=0;
    47. write(client_socket,text_http_ok,strlen(text_http_ok));
    48. if (position1 = strstr(empfangen,"GET"))
    49. {
    50. if (position2 = strstr(empfangen,"HTTP"))
    51. {
    52. laenge = position2 - position1 - 6;
    53. strncpy(dateiname,position1+5,laenge);
    54. dateiname[laenge]=0;
    55. printf("\n GET Befehl für Datei %s gefunden",dateiname);
    56. datei = fopen(dateiname,"rt");
    57. if (datei==NULL)
    58. {
    59. printf("\n Datei existiert nicht");
    60. write(client_socket,text_html_anfang,strlen(text_html_anfang));
    61. write(client_socket,"<br>Datei existiert nicht",25);
    62. write(client_socket,text_html_ende,strlen(text_html_ende));
    63. }
    64. else
    65. {
    66. printf("\n Sende Datei %s",dateiname);
    67. do
    68. {
    69. zeichen = fgetc(datei);
    70. if (!feof(datei))
    71. {
    72. write(client_socket,&zeichen,1);
    73. }
    74. } while (!feof(datei));
    75. fclose(datei);
    76. }
    77. }
    78. else
    79. {
    80. printf("\n Der HTTP-Parser hat keinen HTTP-Befehl gefunden");
    81. write(client_socket,text_html_anfang,strlen(text_html_anfang));
    82. write(client_socket,"kein HTTP-Befehl gefunden",25);
    83. write(client_socket,text_html_ende,strlen(text_html_ende));
    84. }
    85. }
    86. else
    87. {
    88. printf("\n Der HTTP-Parser hat keinen GET-Befehl gefunden");
    89. write(client_socket,text_html_anfang,strlen(text_html_anfang));
    90. write(client_socket,"kein GET-Befehl gefunden",24);
    91. write(client_socket,text_html_ende,strlen(text_html_ende));
    92. }
    93. printf("\n");
    94. close(client_socket);
    95. }
    96. }
    Alles anzeigen
    Open Source --> Programmieren aus Leidenschaft :!:

    Ich stehe weder für privaten Support per PM noch über einen IM zur Verfügung. Danke.
  • while(1), fork()

    Hi Deadman44, da ich kein Programmierer bin, war mir nicht bewusst, dass ich den Code da so reinklatsche und Durch Dein formatieren ist mir bewusst geworden, wie schön der jetzt zu Lesen ist. Finde das sehr nett von Dir. Habe in Zeile 34 von Deinem Code als Port 80 eingetragen und das Programm übersetzt. Dabei passiert folgendes:


    Programm gestartet:

    root@j23764:/home/se# ./a.out

    Der Server wartet...

    Client fordert die Datei bla an:
    root@j23764:~# wget 127.0.0.1/bla

    Jetzt meldet der Client, dass er mit 127.0.0.1:80 connected ist und versucht die Datei zu speichern. Beim Server steht folgendes:

    Verbindung mit 127.0.0.1
    Get Befehl für Datei bla gefunden
    Sende Datei bla

    Es passiert aber nichts. Erst nachdem ich beim Client wget mit STRG+C abbreche, wird die Datei runtergeladen. Ohne fork() arbeitet das Script sauber. Vielleicht hättest Du ja noch einen Tip für mich.

    Viele Grüße

  • Ich habe nun den/die Fehler gefunden und den Code angepasst.

    Quellcode

    1. /*****************************************************************/
    2. /* Dateiname : ServerDateiSenden.c */
    3. /* Beschreibung: Server-Programm */
    4. /* Analysiert einen HTTP-GET-Befehl und versucht */
    5. /* die angeforderte Datei zu senden */
    6. /*****************************************************************/
    7. #include <sys/types.h>
    8. #include <sys/socket.h>
    9. #include <unistd.h>
    10. #include <stdio.h>
    11. #include <stdlib.h> // Für EXIT_SUCCESS eingebunden
    12. #include <netinet/in.h>
    13. #include <arpa/inet.h>
    14. #include <string.h>
    15. int main()
    16. {
    17. int server_socket, client_socket;
    18. int anzahl, laenge, childpid;
    19. struct sockaddr_in serverinfo, clientinfo;
    20. char zeichen;
    21. char empfangen[1000];
    22. char *position1, *position2;
    23. char dateiname[100];
    24. char text_http_ok[] = "HTTP/1.0 200 OK\r\n\r\n";
    25. char text_html_anfang[] = "<HTML><BODY>";
    26. char text_html_ende[] = "</BODY></HTML>";
    27. FILE *datei;
    28. server_socket = socket(AF_INET, SOCK_STREAM, 0);
    29. serverinfo.sin_family = AF_INET;
    30. serverinfo.sin_addr.s_addr = htonl(INADDR_ANY);
    31. serverinfo.sin_port = htons(80);
    32. laenge = sizeof(serverinfo);
    33. bind(server_socket, (struct sockaddr *)&serverinfo, laenge);
    34. listen(server_socket, 3);
    35. while (1)
    36. {
    37. printf("\n Der Server wartet...");
    38. fflush(stdout);
    39. client_socket = accept(server_socket, (struct sockaddr *)&clientinfo, &laenge);
    40. printf("\n Verbindung mit %s",inet_ntoa(clientinfo.sin_addr));
    41. childpid = fork();
    42. if (childpid != 0) // Falls Serverprozess, also Parent, wird die Schleife wiederholt und auf dem Port gelauscht
    43. {
    44. close(client_socket);
    45. }
    46. else // Code für Kindprozess, also für das Bearbeiten der Abfrage
    47. {
    48. close(server_socket);
    49. anzahl = read(client_socket,empfangen,sizeof(empfangen));
    50. empfangen[anzahl]=0;
    51. write(client_socket,text_http_ok,strlen(text_http_ok));
    52. if (position1 = strstr(empfangen,"GET"))
    53. {
    54. if (position2 = strstr(empfangen,"HTTP"))
    55. {
    56. laenge = position2 - position1 - 6;
    57. strncpy(dateiname,position1+5,laenge);
    58. dateiname[laenge]=0;
    59. printf("\n GET Befehl für Datei %s gefunden",dateiname);
    60. datei = fopen(dateiname,"rt");
    61. if (datei==NULL)
    62. {
    63. printf("\n Datei existiert nicht");
    64. write(client_socket,text_html_anfang,strlen(text_html_anfang));
    65. write(client_socket,"<br>Datei existiert nicht",25);
    66. write(client_socket,text_html_ende,strlen(text_html_ende));
    67. }
    68. else
    69. {
    70. printf("\n Sende Datei %s",dateiname);
    71. do
    72. {
    73. zeichen = fgetc(datei);
    74. if (!feof(datei))
    75. {
    76. write(client_socket,&zeichen,1);
    77. }
    78. } while (!feof(datei));
    79. fclose(datei);
    80. }
    81. }
    82. else
    83. {
    84. printf("\n Der HTTP-Parser hat keinen HTTP-Befehl gefunden");
    85. write(client_socket,text_html_anfang,strlen(text_html_anfang));
    86. write(client_socket,"kein HTTP-Befehl gefunden",25);
    87. write(client_socket,text_html_ende,strlen(text_html_ende));
    88. }
    89. }
    90. else
    91. {
    92. printf("\n Der HTTP-Parser hat keinen GET-Befehl gefunden");
    93. write(client_socket,text_html_anfang,strlen(text_html_anfang));
    94. write(client_socket,"kein GET-Befehl gefunden",24);
    95. write(client_socket,text_html_ende,strlen(text_html_ende));
    96. }
    97. printf("\n");
    98. close(client_socket);
    99. return EXIT_SUCCESS; // Kindprozess beenden, da Anfrage bearbeitet wurde
    100. }
    101. }
    102. }
    Alles anzeigen

    Hauptsächlich lag es daran, dass du beim Forken nicht ausreichend zwischen Parent und Child unterschieden hast. Child muss z. Bsp. am Ende terminieren und Parent sollte nicht noch durch den Child-Code laufen. Habe meine Änderungen kurz kommentiert, damit du sie nachvollziehen kannst.
    Open Source --> Programmieren aus Leidenschaft :!:

    Ich stehe weder für privaten Support per PM noch über einen IM zur Verfügung. Danke.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Deadman44 ()