C 线程 Http 服务器错误

C Thread Http Server Error

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

我现在遇到线程问题。该线程工作但出现

错误

"curl: (56) Recv failure: Connection reset by peer"

这是因为我的线程转到响应函数中的那一行。请放心,除了 clients[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", "3[92m", PORT, "3[0m", "3[92m", ROOT, "3[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;
}

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

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

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

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

启动线程后,你的主进程改变 slot.

最佳情况:新线程启动并获取插槽的 new 值,使得 connections[slot] == -1。最坏的情况:线程在不同的 CPU 内核上运行并获得 slot main 正在写入它,导致错误值。

您可能需要考虑将 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?
}