2

Cで単純なHTTPサーバーを1つ作成しようとしていますが、プラットフォーム、Cookieなどを確認するためにブラウザのリクエストを取得する必要があります...そのために、fgets関数でsockファイルを読み取ろうとしていますが、無限に返されますループ。

私のコードを見てください。

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pthread.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdbool.h>

#define SERVER          "TestServer4"               //Servername
#define PROTOCOL        "HTTP/1.1"                  //Protocol used
#define RFC1123FMT      "%a, %d %b %Y %H:%M:%S GMT" //Date format of returns
#define PORT            7777                        //Socket port
#define NUM_THREADS     5                           //Threads clusters numbers

int sock; //Stores the socket

void send_headers(FILE *f, int status, char *title, char *extra, char *mime, int length, time_t date) {
    time_t now;
    char timebuf[128];

    fprintf(f, "%s %d %s\r\n", PROTOCOL, status, title);
    fprintf(f, "Server: %s\r\n", SERVER);
    now = time(NULL);
    strftime(timebuf, sizeof (timebuf), RFC1123FMT, gmtime(&now));
    fprintf(f, "Date: %s\r\n", timebuf);
    if (extra) fprintf(f, "%s\r\n", extra);
    if (mime) fprintf(f, "Content-Type: %s\r\n", mime);
    if (length >= 0) fprintf(f, "Content-Length: %d\r\n", length);
    if (date != -1) {
        strftime(timebuf, sizeof (timebuf), RFC1123FMT, gmtime(&date));
        fprintf(f, "Last-Modified: %s\r\n", timebuf);
    }
    fprintf(f, "Connection: close\r\n");
    fprintf(f, "\r\n");
}

void send_error(FILE *f, int status, char *title, char *extra, char *text) {
    send_headers(f, status, title, extra, "text/html", -1, -1);
    fprintf(f, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title);
    fprintf(f, "<BODY><H4>%d %s</H4>\r\n", status, title);
    fprintf(f, "%s\r\n", text);
    fprintf(f, "</BODY></HTML>\r\n");
}

void get_request(FILE *f) {
    char buf[4096];

    while (fgets(buf, sizeof(buf), f) != NULL) {        
        fgets(buf, sizeof(buf), f);

        printf("%s", buf);
    }

}

int process(FILE *f, long tid) {
    char buf[4096];
    char *method;
    char *path;
    char *protocol;

    struct stat statbuf;  

    if (!fgets(buf, sizeof(buf), f))  return -1;

    get_request(f);

    method = strtok(buf, " ");
    path = strtok(NULL, " ");
    protocol = strtok(NULL, "\r");
    if (!method || !path || !protocol) return -1;

    fseek(f, 0, SEEK_CUR); // Force change of stream direction

    if (strcasecmp(method, "GET") != 0) {
        send_error(f, 501, "Not supported", NULL, "Method is not supported.");
    } else {             
        send_headers(f, 200, "OK", NULL, "text/html", -1, statbuf.st_mtime);

        bool page = !strcmp(path, "/photos.json");

        if (page) {
           fprintf(f, "<b> yeah, photos stream :) </b>"); 
        }  else {           
           fprintf(f, "<HTML><HEAD><TITLE>Yeah</TITLE></HEAD>\r\n<BODY>");
           fprintf(f, "<H4>server (%s) </H4>\r\n<PRE>\n", path); 
        }         
    }

    printf("Im running in thread #%ld!\n", tid); 
    fclose(f);
    return 0;
}

void accept_conn(void *threadid) {
    long tid;
    tid = (long) threadid;

    while (1) {
        int s;
        FILE *f;        

        s = accept(sock, NULL, NULL);
        if (s < 0) { 
            break;
        } else {                    
            f = fdopen(s, "a+");   
            process(f, tid);                   
        };
    }
}

int main(int argc, char *argv[]) {

    struct sockaddr_in sin;

    sock = socket(AF_INET, SOCK_STREAM, 0);

    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(PORT);
    bind(sock, (struct sockaddr *) &sin, sizeof (sin));

    listen(sock, 5);
    printf("HTTP server listening on port %d\n", PORT);

    pthread_t threads[NUM_THREADS];
    int rc;
    long t;
    for (t = 0; t < NUM_THREADS; t++) {
        printf("In main: creating thread %ld\n", t);
        rc = pthread_create(&threads[t], NULL, accept_conn, (void *) t);
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }

    /* Last thing that main() should do */
    pthread_exit(NULL);

    close(sock);
    return 0;
}

問題は get_request 関数にあります。

4

1 に答える 1

1

何が起こっているかというとfgets、http リクエストの最後、つまり"\r\n". ファイルではなく、ソケットから読み取っています。

あなたがする必要があるのは、このようなものです。また、後でバッファーを使用して何かを実行できるように、バッファーとその長さを渡す必要があります。

void
get_request(FILE *f, char *buf, int len)
{
    int n;
    char *p = buf;

    while (1) {
        fgets(p, len, f);

        if (strcmp(p, "\r\n") == 0) {
            break;
        }

        n = strlen(p);
        p += n;
        len -= n;
    }

    printf("req = %s\n", buf);
}
于 2012-12-14T20:11:23.957 に答える