0

HTMLページまたはエラーページをブラウザに送信するだけの小さなWebサーバーを作成しました。私の新しいソケットの知識を練習するためだけに。

このプログラムでは、select メソッドを使用して複数のリクエストを処理しようとしていました。

プログラムは接続を受け入れますが、何も起こりません... Firefox は引き続きファイルをロードしますが、ファイルは表示されず、プログラムは何もしません (ただし、クラッシュはしません)。

これは私のコードです:

#include <stdio.h>
#include <winsock2.h>
#include <winsock.h>
#include <Ws2tcpip.h>
#include <time.h>

#pragma comment(lib, "ws2_32.lib" )
#define BUFFSIZE 512
#define PORT "9001"
#define MAXCONNECTIONS 10

char * getPath(char * input, int var, char result[]);
void sendHeader(char * ext, char *path, int socketDescr, int code);
void sendBody(char * ext, char *path, int socketDescr, int code);


int main()
{
    WSADATA wsaData;
    struct timeval tv;  // timeinterval for request (should arrive in less than 2seconds)
    fd_set master;      // keeps track of all open file descriptors + listener
    fd_set read_fds;    // list of file descriptors to read from
    int fdmax;          // max file descriptor number
    int listener;       // file descriptor on socket
    int newfd;          // new client file descriptor
    struct sockaddr_storage clientaddr; // client address
    socklen_t addrlen;  // length of address
    char clientIP[INET_ADDRSTRLEN]; // client ip-address (ipv4)
    char buffer[BUFFSIZE]; // buffer for request
    char request[BUFFSIZE]; // buffer for request
    int recvbytes;      // amount of bytes received
    int yes = 1;        // reuse address
    int i,rv;
    struct addrinfo serverinfo, *socketlist, *sock;

    char result[BUFFSIZE];
    char  * path;
    char * extension;

    if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0) 
    {
        fprintf(stderr, "WSAStartup failed.\n");
        exit(1);
    }

    // Set up time interval
    tv.tv_sec = 5;
    tv.tv_usec = 0;

    // Clean up file descriptor sets
    FD_ZERO(&master);
    FD_ZERO(&read_fds);

    // Get a socket and bind for listening
    memset(&serverinfo, 0, sizeof(serverinfo));
    serverinfo.ai_family = AF_INET;
    serverinfo.ai_socktype = SOCK_STREAM; // TCP
    serverinfo.ai_flags = AI_PASSIVE; // we search a socket on our side (server side) for listening

    if((rv = getaddrinfo(NULL,PORT,&serverinfo,&socketlist)) != 0)
    {
        fprintf(stderr,"Server: %s\n",gai_strerror(rv));
        exit(1);
    }

    // loop trough sockets
    for(sock = socketlist; sock != NULL; sock = sock->ai_next)
    {
        listener = socket(sock->ai_family, sock->ai_socktype, sock->ai_protocol);
        if(listener < 0)
        {
            continue; // not correct socket
        }
        setsockopt(listener,SOL_SOCKET,SO_REUSEADDR, &yes, sizeof(int));
        if(bind(listener, sock->ai_addr, sock->ai_addrlen) < 0)
        {
            closesocket(listener);
            continue; // could not bind to socket
        }
        break;
    }

    // if could not get socket
    if(sock == NULL)
    {
        fprintf(stderr,"Server: %s\n","Could not bind to socket");
        exit(2);
    }

    // free up list, we have the socket
    freeaddrinfo(socketlist);

    // listen on socket
    if(listen(listener,MAXCONNECTIONS) < 0)
    {
        perror("Server: listen");
        exit(3);
    }

    // add listener to master set
    FD_SET(listener,&master);
    fdmax = listener;
    fprintf(stdout,"Server: %s\n","Waiting for connections...");

    for(;;)
    {
        read_fds = master;
        if(select(fdmax+1,&read_fds,NULL,NULL,&tv) < 0)
        {
            perror("Server: select");
            exit(4);
        }

        // run through existing connections to see if request has arrived
        for(i = 0; i <= fdmax; i++)
        {
            if(FD_ISSET(i, &read_fds))
            {
                if(i == listener)
                {
                    // we have a new connection
                    addrlen = sizeof clientaddr;
                    if((newfd = accept(listener,(struct sockaddr*)&clientaddr,&addrlen)) < 0)
                    {
                        perror("Server: accept");
                        exit(5);
                    }
                    else
                    {
                        FD_SET(newfd,&master);
                        if(newfd > fdmax)
                        {
                            fdmax = newfd;
                        }
                        fprintf(stdout, "Server: New connection from %s on socket %d\n",inet_ntop(clientaddr.ss_family, &(((struct sockaddr_in*)((struct sockaddr*)&clientaddr))->sin_addr), clientIP, sizeof(clientIP)),newfd);
                    }
                }
                else
                {
                    // handle data from request
                    if((recvbytes = recv(i,buffer,BUFFSIZE-1,0)) <= 0)
                    {
                        if(recvbytes == 0) //connection closed
                        {
                            fprintf(stdout,"Server: socket %d goodbye\n",i);
                        }
                        else //request error [BAD REQUEST]
                        {
                            perror("Server: recv");
                        }
                        closesocket(i);
                        FD_CLR(i,&master);
                    }
                    else
                    {
                        recvbytes = recv(i, buffer,BUFFSIZE-1 , 0);
                        if(recvbytes > 0)
                        {
                            buffer[recvbytes]='\0';
                            strcat(request,buffer);
                        }
                        fprintf(stdout,"Server: request received:\n");
                        printf("%s", request);

                        //Get path
                        path = getPath(request,0, result);
                        if(strcmp(path,"error") != 0)
                        {
                            extension = getPath(request,1,result);
                            if(strcmp(extension,"error") != 0)
                            {
                                // send file 200
                                sendBody(extension,path,i,200);
                            }
                        }
                        else
                        {
                            // send code 400
                            sendBody("html","400.html",i,400);
                        }

                        closesocket(i);
                        FD_CLR(i,&master);
                    }
                }
            }
        }
    }
    return 0;
}

// Gives path, extension of file or error
char * getPath(char * input, int var, char result [])
{
    char * pch;
    char str[BUFFSIZE];
    strcpy(str,input);

    pch = strtok(str,"\r\n");
    pch = strtok(pch," ");

    if(strcmp(pch,"GET") != 0)
    {
        strcpy(result,"error");
        return result;
    }

    pch = strtok(NULL," ");
    if(var == 0)
    {
        strcpy(result,pch);
        return result; 
    }
    pch = strtok(pch,".");
    pch = strtok(NULL,".");
    if(var == 1)
    {
        strcpy(result,pch);
        return result;
    }

    return 0;
}

//Send header
void sendHeader(char * ext, char *path, int socketDescr, int code)
{
    FILE * fp;
    int fileSize = 0;
    char fileSizeChar[32];
    char * header;
    char * status;
    char * contenType;
    char * contentLength;
    char * msg;

    if((fp = fopen(path, "r")) == NULL)
    {
        printf("Error opening file %s\n",path);
        return;
    }
    //Get filesize
    fseek(fp, 0L, SEEK_END);
    fileSize = ftell(fp);
    fseek(fp, 0L, SEEK_SET);
    fclose(fp);

    //Create header response message
    header = "HTTP/1.0 ";

    if(code == 200)
        strcpy(status,"200");
    else if(code == 400)
        strcpy(status,"400");
    else if(code == 404)
        strcpy(status,"404");

    if(strcmp(ext,"html") == 0)
        strcpy(contenType," text/html\n");

    //create and send header
    strcat(msg,header);
    strcat(msg,status);
    strcat(msg,contenType);
    strcat(msg,contentLength);
    strcat(msg,fileSizeChar);

    send(socketDescr, msg, strlen(msg), 0);
}

//Sending data like, pictures, zip, html pages... or an error html page
void sendBody(char * ext, char *path, int socketDescr, int code)
{
    FILE * fp;
    int fileSize = 0;
    int sendBytes = 0;
    int resultRead;
    int resultSend;
    char buffer[1000];

    if((fp = fopen(path, "r")) == NULL)
    {
        printf("Can't open file %s\n",path);
        if(code == 400)
        {
            printf("Error page 400 doesn't exist.\n");
            return;
        }
        if((fp = fopen("404.html","r")) == NULL)
        {
            printf("Error page 404 doesn't exist.\n");
            return;
        }
        strcpy(ext,"html");
        strcpy(path,"404.html");
        code = 404;
    }

    sendHeader(ext,path,socketDescr,code);

    fseek(fp, 0L, SEEK_END);
    fileSize = ftell(fp);
    fseek(fp, 0L, SEEK_SET);

    while(sendBytes < fileSize)
    {
        fseek(fp,sendBytes,SEEK_SET);
        resultRead = fread(buffer,sizeof buffer[0],1000,fp);
        resultSend = send(socketDescr,buffer,resultRead,NULL);
        sendBytes +=resultSend;
    }
    fclose(fp);
}

表示される唯一の行は「サーバー: ソケット上の %s からの新しい接続」です。

誰か助けてくれませんか?

敬具、

4

1 に答える 1

1

ここにコメントするには情報が多すぎます-しかし、これは他の人があなたの問題を解決するのに役立つかもしれません:

私はあなたのコードをコンパイルして実行しました。デバッガーを見ると、サーバーは入力を待ってブロックされていると思います

                recvbytes = recv(i, buffer,BUFFSIZE-1 , 0);

コンソール

サーバー: 接続を待機しています... サーバー: ソケット 120 上の 127.0.0.1 からの新しい接続 サーバー: ソケット 124 上の 127.0.0.1 からの新しい接続

私のバッファには(440文字)があります:

  • buffer 0x0028f668 "GET / HTTP/1.1\r\nHost: localhost:9001\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML、Gecko など) Chrome/22.0.1229.94 Safari/537.4\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9, / ;q=0.8\r\nAccept-Encoding: gzip,deflate,sdch\r \nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r \ ncookie:plushcontainerwidth = 100%25; plushnotopmenu = 0 \ r \ n \ r \nììììetuuuかesrìììかuルゥピを寄せ格に

とマイブラウザが待っています。

別のリクエストを送信しましたが、クラッシュしました-したがって、recv がブロックされていると思われます (呼び出しで使用できるオプションを参照してください) バッファがいっぱいになるのを待っている可能性があります。

この時点で、要求にデータがなかったため、GetPath でクラッシュが発生しました。これは、recv 呼び出しが 0 バイトを返したためです。

お役に立てれば。

于 2012-11-01T23:33:22.957 に答える