0

奇怪的。我可以使用本地机器上包含的代码发出 GET 请求,它就像一个魅力。从本地机器命令行,使用GET -Ue 192.168.2.106:8129我得到

200 OK
Content-Length: 296
Content-Type: text/html
Client-Date: Sat, 09 Feb 2013 20:26:09 GMT
Client-Response-Num: 1

<html><body><h1>Directory</h1><a href=/.>.</a><br/><a href=/..>..</a><br/><a href=/bldg.jpg>bldg.jpg</a><br/><a href=/hello.txt>hello.txt</a><br/><a href=/world.gif>world.gif</a><br/><a href=/index.html>index.html</a><br/><a href=/testing>testing</a><br/><a href=/favicon.ico>favicon.ico</a><br/>

从我得到的远程机器那里

200 OK
Content-Length: 328
Content-Type: text/html
Client-Aborted: die
Client-Date: Sat, 09 Feb 2013 20:25:16 GMT
Client-Response-Num: 1
X-Died: read failed: Connection reset by peer at /usr/share/perl5/LWP/Protocol/http.pm line 414.

第二个看起来想要工作,但不稳定的“X-Died”标题很奇怪。我偷偷怀疑我的 GetLine 方法已关闭,但我不太确定。知道什么可能导致这个问题吗?

主功能:

int main(int argc, char* argv[])
{
    // First set up the signal handler
    struct sigaction sigold, signew;

    signew.sa_handler = handler;
    sigemptyset(&signew.sa_mask);
    sigaddset(&signew.sa_mask, SIGPIPE);
    signew.sa_flags = SA_RESTART;
    sigaction(SIGPIPE, &signew, &sigold);

    int     hSocket,hServerSocket;  /* handle to socket */
    struct  hostent* pHostInfo;     /* holds info about a machine */
    struct  sockaddr_in Address;    /* Internet socket address stuct */
    int     nAddressSize=sizeof(struct sockaddr_in);
    char    pBuffer[BUFFER_SIZE];
    int     nHostPort;

    q = new myQueue();

    // THREAD POOL!
    pthread_t thread_id[NUMTHREADS];
    int i=0;
    for(i=0; i < NUMTHREADS; i++)
    {
        threadParams param;
        param.a = i;
        pthread_create(&thread_id[i], 0, &WorkerHandler, NULL);
    }

    if(argc < 2)
    {
        printf("\nUsage: server host-port\n");
        return 0;
    }
    else
    {
        nHostPort = atoi(argv[1]);
    }

    printf("\nStarting server");
    printf("\nMaking socket");

    /* make a socket */
    hServerSocket=socket(AF_INET,SOCK_STREAM,0);

    if(hServerSocket == SOCKET_ERROR)
    {
        printf("\nCould not make a socket\n");
        return 0;
    }

    /* fill address struct */
    Address.sin_addr.s_addr=INADDR_ANY;
    Address.sin_port=htons(nHostPort);
    Address.sin_family=AF_INET;

    printf("\nBinding to port %d",nHostPort);

    int optval = 1;
    setsockopt(hServerSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

    /* bind to a port */
    if(bind(hServerSocket,(struct sockaddr*)&Address,sizeof(Address)) == SOCKET_ERROR)
    {
        printf("\nCould not connect to host\n");
        return 0;
    }

    /*  get port number */
    getsockname( hServerSocket, (struct sockaddr *) &Address,(socklen_t *)&nAddressSize);
    printf("opened socket as fd (%d) on port (%d) for stream i/o\n",hServerSocket, ntohs(Address.sin_port) );

    printf("Server\n\
             sin_family        = %d\n\
             sin_addr.s_addr   = %d\n\
             sin_port          = %d\n"
             , Address.sin_family
             , Address.sin_addr.s_addr
             , ntohs(Address.sin_port));

    /* establish listen queue */
    if(listen(hServerSocket, 1000) == SOCKET_ERROR)
    {
        printf("\nCould not listen\n");
        return 0;
    }

    while(1)
    {
        int socket = accept(hServerSocket, (struct sockaddr*)&Address, (socklen_t *)&nAddressSize);
        q->enqueue(socket);
    }
}

void handler (int status)
{
}

处理套接字上的请求:

int handleRequest(int socket)
{
    cout << "handling a request..." << endl;

    // Get the URL
    char * line = GetLine(socket);

    //char * line = "GET /bldg.jpg HTTP/1.1";
    char * url;
    url = strtok(line, " "); // Splits spaces between words in str
    url = strtok(NULL, " "); // Splits spaces between words in str

    // build filename
    ostringstream fullpathstream;
    fullpathstream << dirpath << url;
    string fullpath = fullpathstream.str();

    //Use the stat function to get the information
    struct stat fileAtt;
    if (stat(fullpath.c_str(), &fileAtt) != 0) //start will be 0 when it succeeds
    {
        cout << "File not found:" << fullpath.c_str() << endl;
        writeError(socket);
        return 0;
    }

    // Make correct filetypes
    if (S_ISREG (fileAtt.st_mode))
    {
        printf ("%s is a regular file.\n", fullpath.c_str());

        char * contentType;
        if(strstr(url, ".jpg"))
        {
            cout << "JPEG" << endl;
            contentType = "image/jpg";
        }
        else if(strstr(url, ".gif"))
        {
            contentType = "image/gif";
            cout << "GIF" << endl;
        }
        else if(strstr(url, ".html"))
        {
            contentType = "text/html";
            cout << "HTML" << endl;
        }
        else if(strstr(url, ".txt"))
        {
            cout << "TXT" << endl;
            contentType = "text/plain";
        }
        else if(strstr(url, ".ico"))
        {
            cout << "ICO" << endl;
            contentType = "image/ico";
        }
        serveFile(fullpath, socket, fileAtt.st_size, contentType);
    }

    if (S_ISDIR (fileAtt.st_mode))
    {
        printf ("%s is a directory.\n", fullpath.c_str());
        serveDirectory(socket, url);
    }

    return 0;
};

GetLine 函数用于获取请求的第一行,因此我知道请求的 URL:

// Read the line one character at a time, looking for the CR
// You dont want to read too far, or you will mess up the content
char * GetLine(int fds)
{
   char tline[MAX_MSG_SZ];
   char *line;

   int messagesize = 0;
   int amtread = 0;
   while((amtread = read(fds, tline + messagesize, 1)) < MAX_MSG_SZ)
   {
       if (amtread > 0)
           messagesize += amtread;
       else
       {
           perror("Socket Error is:");
           fprintf(stderr, "Read Failed on file descriptor %d messagesize = %d\n", fds, messagesize);
           exit(2);
       }
       //fprintf(stderr,"%d[%c]", messagesize,message[messagesize-1]);
       if (tline[messagesize - 1] == '\n')
           break;
   }
   tline[messagesize] = '\0';
   chomp(tline);
   line = (char *)malloc((strlen(tline) + 1) * sizeof(char));
   strcpy(line, tline);
   //fprintf(stderr, "GetLine: [%s]\n", line);
   return line;
}

我发生了多线程,这就是我关闭套接字的地方。

void * WorkerHandler(void *arg)
{
    threadParams* params = (threadParams*)arg;
    while(1)
    {
        int socket = q->dequeue();
        handleRequest(socket);
        if(close(socket) == SOCKET_ERROR)
        {
            printf("\nCould not close socket\n");
            return 0;
        }
    }
}
4

0 回答 0