每个客户端一个线程的 UDP 回显服务器

UDP echo server with one thread per client

我有一个简单的 TCP 回显服务器,每个客户端一个线程(它可以工作),所以我试图将它转换为 UDP,但在 运行 server:

之后遇到了问题

"pthread_create() resource temporarily unavailable"

。这是我的服务器代码:

#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

#define PORT 1027
#define BACKLOG 5
#define MAXLINE 256

#define SA struct sockaddr

typedef struct serve_clientArg {
    int socket;
    SA *addr;
    socklen_t addrlen;
} SCARGS;

void Pthread_create(pthread_t *thread, pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)
{
    int rc;

    rc = pthread_create(thread, attr, start_routine, arg);
    if(rc) {
        errno = rc;
        error("pthread_create()");
    }
}

reads()writen() 正在使用 recvfrom()sendto() 函数

void *serve_client(void* arg)
{
    char s[MAXLINE];
    ssize_t rc;
    SCARGS *args = Malloc(sizeof (SCARGS));
    args = (SCARGS*) arg;
    int socket = args->socket;
    SA *addr = args->addr;
    socklen_t addrlen = args->addrlen;
    free(arg);

    pthread_detach(pthread_self());

    while((rc = reads(socket, s, MAXLINE, addr, &addrlen)) > 0) {
        writen(socket, s, rc, addr, addrlen);
    }
    Close(socket);

    return NULL;
}

int main(void)
{
    int socket;
    struct sockaddr_in servaddr;
    struct sockaddr_in cliaddr;
    SCARGS *arg;
    pthread_t thread;

    socket = Socket(AF_INET, SOCK_DGRAM, 0);

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    Bind(socket, (SA *) &servaddr, sizeof(servaddr));

    for(;;) {
        arg = Malloc(sizeof (SCARGS));
        arg->socket = socket;
        arg->addr = (SA*) &cliaddr;
        arg->addrlen = sizeof (cliaddr);

        Pthread_create(&thread, NULL, serve_client, (void*) arg);
    }

    return 0;
}

我也有一个 TCP 客户端,在转换为 UDP 后它可以工作。我想我犯了一个愚蠢的错误,但我找不到...请帮我找到错误!

for(;;) {
    arg = Malloc(sizeof (SCARGS));
    arg->socket = socket;
    arg->addr = (SA*) &cliaddr;
    arg->addrlen = sizeof (cliaddr);

    Pthread_create(&thread, NULL, serve_client, (void*) arg);
}

您可以在没有任何阻塞的无限循环中分配内存并创建新线程(就像您在 TCP 中使用 accept 所做的那样)。因此它很快就会耗尽资源:

"pthread_create() resource temporarily unavailable"

除此之外,您在所有线程中使用相同的套接字。但是当你只有一个套接字时,让多个线程处理它就没有意义了。我不确定你想通过这个设计实现什么。