简体   繁体   English

服务器停止创建线程

[英]server stops creating threads

I have a very simple client-server code. 我有一个非常简单的客户端-服务器代码。 Every time a server receives a packet I create a thread that handles it. 每当服务器收到一个数据包时,我都会创建一个处理它的线程。 The code is shown below. 代码如下所示。 What I can't understand is that after sometime my server stops receiving any data. 我不明白的是,一段时间后我的服务器停止接收任何数据。 It just listens and doesn't receive anything. 它只是在听,什么也没收到。 I can't figure out why. 我不知道为什么。 Does anyone know the reason. 有谁知道原因。

I'm building my code on Lenovo T470s Fedora 29, Linux user 4.19.15-300.fc29.x86_64 #1 SMP Mon Jan 14 16:32:35 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux 我在Lenovo T470s Fedora 29,Linux用户4.19.15-300.fc29.x86_64#1 SMP星期一1月14日16:32:35 UTC 2019 x86_64 x86_64 x86_64 GNU / Linux上构建代码

Any help is appreciated. 任何帮助表示赞赏。

/* 
  server.c
  cc -std=gnu11 -pedantic  -lpthread  server.c   -o server.c 
 */

#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define BUF_SIZE_B 1024

static int fd;

static void *handlePacketThreadWrapper(void *arg);

int main(void)
{
    pthread_t t;
    struct pollfd pollfd;
    struct sockaddr_in addr;
    uint16_t port = 9500;

    fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    if (fd < 0)
    {
        printf("errno: %d. %s. Failed to create a socket",
                errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    addr.sin_family      = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port        = htons(port);

    while(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        printf("errno: %d. %s. Failed to bind socket. Will attempt again.", errno,
                strerror(errno));
        sleep(1);
    }

    memset(&addr, 0, sizeof(addr));

    pollfd.fd = fd;
    pollfd.events = POLLIN;

    while(true)
    {

        if (poll(&pollfd, 1, -1) < 0)
        {
            printf("errno: %d. %s", errno, strerror(errno));
        }
        else
        {
            pthread_create(&t, NULL, handlePacketThreadWrapper, NULL);
        }
    }

    return 0;
}

static void *handlePacketThreadWrapper(void *arg)
{
    uint8_t buf[BUF_SIZE_B];
    size_t strLen, fullIPLen;
    ssize_t
        i,
        n
        ;
    struct sockaddr_in addr;
    socklen_t addrLen = sizeof(addr);
    char *str, *fullIP;


    n = recvfrom(fd, buf, sizeof(buf), 0,
            (struct sockaddr *)&addr, (socklen_t *)&addrLen);
    if (n < 0)
    {
        printf("errno: %d. %s. Failed to create a socket",
                errno, strerror(errno));
    }
    else
    {
        for (i = 0; i < n; i++)
        {
            printf("0x%02X ", buf[i]);
        }
        printf("\n");
    }
    return NULL;
}

And here is my client code: 这是我的客户代码:

/* 
  client.c
  cc -std=gnu11 -pedantic  client.c   -o client.c  
 */
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>

#define BUF_SIZE_B 1024

int main(void)
{
    ssize_t size, i;
    struct sockaddr_in dest;
    int fd;
    char *toIP = "127.0.0.1";
    uint16_t toPort = 9500;
    uint8_t buf[BUF_SIZE_B];

    fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (fd < 0)
    {
        printf("errno: %d, %s", errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    memset(&dest, 0, sizeof(dest));
    dest.sin_family      = AF_INET;
    dest.sin_addr.s_addr = inet_addr(toIP);
    dest.sin_port        = htons(toPort);

    while(true)
    {
        size = sendto(fd, buf, sizeof(buf), 0, (struct sockaddr*)&dest, sizeof(dest));
        if (size < 0)
        {
            printf("errno: %d. %s. Failed to send bytes to %s:%hu.", 
                    errno, strerror(errno), toIP, toPort);
        }
        else
        {
            for (i = 0; i < size; i++)
                printf("0x%02X ", buf[i]);
            printf("\n");
        }
        usleep(1000);
    }

    return 0;
}

You can only have as many threads running simultaneously, as ulimit -u reports. 根据ulimit -u报告,您只能同时运行多个线程。

Your server never joins the threads, and once the limit is reached it starts failing to create them. 您的服务器从不加入线程,一旦达到限制,它就开始无法创建线程。

In your server the main thread and the created thread(s) access the same socket ( fd ) without any protection like exclusive section, so the execution of poll and recvfrom can be done in any order including simultaneously , that probably destruct the internal data of the socket. 在您的服务器中, 线程和创建的线程在没有任何保护(例如独占节)的情况下访问相同的套接字( fd ),因此可以按任意顺序(包括同时执行)执行pollrecvfrom ,这很可能破坏了内部数据。插座。

You can do for example : 您可以例如:

while(true)
{

    if (poll(&pollfd, 1, -1) < 0)
    {
        printf("errno: %d. %s", errno, strerror(errno));
    }
    else
    {
        pthread_create(&t, NULL, handlePacketThreadWrapper, NULL);
        pthread_join(&t);
    }
}

That both protect the use of the socket and avoid zombie thread as mentioned by user58697 in an other answer (the threads are not detached by default). 这样既可以保护套接字的使用,又可以避免在另一个答案中提到user58697提到的僵尸线程 (默认情况下不分离线程)。

Of course doing that limit the interest to read on the socket in an other thread, but your code is not really compatible with multi threading for several reasons 当然,这样做会限制在其他线程中读取套接字的兴趣,但是由于多种原因,您的代码实际上与多线程不兼容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM