C线程Http服务器错误

时间:2016-10-19 23:49:14

标签: c multithreading simplehttpserver

我正在练习通过能够接受来自多个客户端的多个响应来使服务器同时运行的不同形式。这是一项学校作业。

我现在遇到线程问题。该线程有效,但出现错误

"卷曲:(56)Recv失败:由同行重置连接"

这是因为我的线程转到了响应函数中的行。请放心,除客户端[n]之外的所有变量都是常量。所以它不是正确的传递,或者我完全错过了应该如何进行线程化的标记。

rcvd = recv(clients[n], mesg, 99999, 0);

这行继续将-1返回到rcvd并且我想要> 0

这是我的代码。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<signal.h>
#include<fcntl.h>
#include<pthread.h>

#include "functions.h"
#define CONNMAX 1000
#define BYTES 1024

char *ROOT;
int verbose;
int signalReceived = 1;
int listenfd, clients[CONNMAX], slot;
pthread_t thread;
void error(char *);

void *threadServer(void *arg)
{
    printf("bong");
    respond(slot, verbose, ROOT, clients);
    exit(0);
}

void clean(int arg)
{
    signalReceived = 0;
}

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

    signal(SIGINT, clean);
    signal(SIGHUP, clean);

    struct sockaddr_in clientaddr;
    socklen_t addrlen;
    char c;
    char PORT[6];
    ROOT = getenv("PWD");
    strcpy(PORT, "8888");
    while ((c = getopt (argc, argv, "p:v")) != -1)

    switch (c)
    {
        case'v':
        verbose = 1;
        break;

        case'p':
        strcpy(PORT, optarg);
        break;

        case'?':
        fprintf(stderr, "Wrong arguments given\n");
        exit(1);

        default:
        exit(1);
    }
    printf("Listening on port %s%s%s, root is %s%s%s\n", "\033[92m", PORT, "\033[0m", "\033[92m", ROOT, "\033[0m");
    int i = 0;
    for (i = 0; i < CONNMAX; i++)
        clients[i] = -1;
    startServer(PORT, &listenfd);

    while (signalReceived == 1)
    {
        addrlen = sizeof(clientaddr);
        clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen);

        if (clients[slot] < 0)
        exit(0);

        else
        {
            printf("bang");
            pthread_create(&thread, NULL, threadServer, NULL);
        }
        while (clients[slot] != -1)
            slot = (slot + 1) % CONNMAX;
    }
    return 0;
}

我正在学习,这不是我最初的源作品,而是为了学习而编辑的作品。我采用了一个分叉的原始程序,现在正尝试将其转换为线程程序。

2 个答案:

答案 0 :(得分:0)

您的threadServer函数调用exit,终止此过程。

我不确定它来自哪里,因为它在调用fork的服务器中也不合适。但它在多线程程序中肯定是致命的。

答案 1 :(得分:0)

slot是一个全局变量。启动一个线程可能需要一段时间,并且线程共享相同的内存。他们没有自己的快照,就像分叉的进程一样。

启动主题后,主进程改变 slot

最佳案例场景:新线程启动并获取插槽的 new 值,使connections[slot] == -1。最坏的情况:线程在不同的CPU核心上运行,并且在 main写入时会获得slot ,从而导致错误值。

您可能需要考虑将slot作为参数传递给线程函数:

void *threadServer(void *arg)
{
    int mySlot = (int)arg;
    printf("bong\n");
    respond(mySlot, verbose, ROOT, clients);
    clients[mySlot] = -1;
    printf("bash\n");
    return NULL;  // calling 'exit' terminates the whole process. duh.
}

// ...

    pthread_create(&thread, NULL, threadServer, (void*)slot);

您在这里遇到的另一个问题是您创建了所有这些线程,但是您没有单独跟踪它们。您可能需要一个线程数组,或者您可能需要考虑一个简单的结构:

typedef struct Clients {
    int fd;
    pthread_t thread;
} Clients;
Clients clients[MAXCONN];

//

while (signalReceived == 1)
{
    addrlen = sizeof(clientaddr);
    clients[slot].fd = accept(listenfd, (struct sockaddr *) &clientaddr, &addrlen);

    if (clients[slot].fd < 0)
        exit(0);
    else
    {
        printf("bang");
        pthread_create(&clients[slot].thread, NULL, threadServer, (void*)slot);
    }

    while (clients[slot] != -1)
        slot = (slot + 1) % CONNMAX;  // what if we can't find one?
}