Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
应用程序是否可以处理N个accept连接,并且每个accept都使用一个独立的线程_C_Linux_Sockets_Linux Kernel_Posix - Fatal编程技术网

应用程序是否可以处理N个accept连接,并且每个accept都使用一个独立的线程

应用程序是否可以处理N个accept连接,并且每个accept都使用一个独立的线程,c,linux,sockets,linux-kernel,posix,C,Linux,Sockets,Linux Kernel,Posix,我有一个C linux TCP客户机/服务器应用程序。 我提出了一个奇怪的场景,但我不知道这个应用程序是否会产生任何后果。 我有一个可以接受N个连接的服务器端,例如,这个服务器将接受100个连接。 在这个场景中,我在主线程中创建侦听套接字,然后创建100个线程,每个线程都有一个独立的accept()和select()iomux,而且每个线程只能接受一个连接 我在这里关心的是,如果两个并发accept()因为select是同一套接字上的ready to read而想要接受同一套接字(连接),我不知

我有一个C linux TCP客户机/服务器应用程序。 我提出了一个奇怪的场景,但我不知道这个应用程序是否会产生任何后果。 我有一个可以接受N个连接的服务器端,例如,这个服务器将接受100个连接。 在这个场景中,我在主线程中创建侦听套接字,然后创建100个线程,每个线程都有一个独立的accept()和select()iomux,而且每个线程只能接受一个连接

我在这里关心的是,如果两个并发accept()因为select是同一套接字上的ready to read而想要接受同一套接字(连接),我不知道并发accept在内核中是否是线程安全的,并且只有一个accept可以处理传入的连接,而另一个将等待另一个连接

我在我的RedHat机器上试过,效果很好,但我不知道我是否幸运地避免了死锁

谢谢

rc = bind(sd, (struct sockaddr_in *)& groupSock, sizeof(struct sockaddr_in));
    CHECK_VALUE("Bind address error", rc, 0, goto cleanup);

    rc = listen(sd, 10);
    CHECK_VALUE("listen", rc, 0, goto cleanup);

    for(; count< num_socks; count++){

            par_data[count].sd = sd;
            par_data[count].thread_num = count;
            par_data[count].err_chk = -1;

            rc = pthread_create(&thread_id[count], NULL, accept_sock_thread,  (void *)& par_data[count]);
            CHECK_VALUE("pthread_create", rc, 0, goto cleanup);


    }

void * accept_sock_thread(void* atr){

    int                     rc;
    int                     sock            = INVALID_SOCKET;
    int                     datalen         = config.traffic;
    char                    *databuf        = NULL;
    struct thread_data      *data           = NULL;
    struct sockaddr_in      tcp_remote;
    struct timeval          t;
    socklen_t               size;
    fd_set                  socks;

    databuf = malloc(sizeof(char) * datalen);
    memset(databuf, 0, datalen);

    data = (struct thread_data*) atr;
    DEBUG(my_debug_flags, ENTER_FUNCT, ("Enter Function accept_sock_thread thread_num %d \n", data->thread_num));


    FD_ZERO(&socks);
    FD_SET(data->sd, &socks);
    t.tv_sec = 25;
    t.tv_usec = 0;
    rc = select(data->sd + 1 , &socks, NULL, NULL,&t);
    if(rc < 0){
            VL_MISC_ERR(("Error in select with Errno: %d", errno));
            goto cleanup;
    }
    else if(rc == 0){
            VL_MISC_ERR(("Accept Select returned a TIEMOUT."));
            goto cleanup;
    }


    size = sizeof(struct sockaddr_in);
    sock = accept(data->sd, (struct sockaddr *)& tcp_remote, &size);
    CHECK_NOT_EQUAL("tcp accept error", sock, INVALID_SOCKET,  goto cleanup);
cleanup:
    //      sleep(2); /* avoid EOF */
    if(sock != INVALID_SOCKET){

            rc = close(sock);
            if(rc != 0){
                    data->err_chk = -1;
            }
    }
           return NULL;
}
rc=bind(sd,(struct sockaddr_in*)和groupSock,sizeof(struct sockaddr_in));
检查_值(“绑定地址错误”,rc,0,转到清除);
rc=听(sd,10);
检查_值(“侦听”,rc,0,转到清除);
对于(;计数thread_num));
FD_零和袜子;
FD_集(数据->sd和socks);
t、 tv_sec=25;
t、 tv_usec=0;
rc=select(数据->sd+1,&socks,NULL,NULL,&t);
if(rc<0){
VL_MISC_ERR((“选择错误,错误号:%d”,错误号));
去清理;
}
else if(rc==0){
VL_MISC_ERR((“接受选择返回一个TIEMOUT”);
去清理;
}
size=sizeof(结构sockaddr_in);
sock=accept(数据->sd,(结构sockaddr*)和tcp_远程和大小);
检查“不相等”(“tcp接受错误”、套接字、无效套接字、转到清除);
清理:
//睡眠(2);/*避免EOF*/
if(sock!=无效的_套接字){
rc=关闭(sock);
如果(rc!=0){
data->err_chk=-1;
}
}
返回NULL;
}
根据POSIX标准,
accept()
是线程安全且可重入的

这意味着对同一描述符的两个accept调用不应给出未定义的行为。一个accept将打开套接字,另一个将返回错误

你可以在那里看到更多:


只有一个线程将接受连接。内核保证了这一点。在unix/posix世界中,这种方式已经存在很长时间了。

只有一个线程会接受(),到目前为止还不错…-但在此之前,所有线程都将被触发,以返回
select()
,这可能不是您想要的

因此,如果您有N个线程睡在
select()
中,并且有一个连接进入中,那么所有的线程都会被唤醒,但只需要一个,因为只有一个可以成功地
接受()
调用。

使用
接受()
对来自多个线程/进程的同一套接字对象进行访问不仅是标准策略,而且也是广泛使用的策略。据我所知,apache就是这样做的nginx也会这样做,但方式略有不同

注意:
select()
可以唤醒多个线程,但其中只有一个线程将接受连接,而其他线程将a挂起
accept()
b)返回-1,并在非阻塞IO的情况下将
errno
设置为EAGAIN。由于您使用的是accept()之前的
select()
,因此我假设套接字描述符处于非阻塞模式。因此,这可能会导致某些线程从未为连接提供服务


另外,我建议您不要在多个线程中关闭同一个套接字。这可能导致非常恶劣和难以调试的后果。使用包装器和
共享\u ptr
或将“套接字所有者”角色分配给其中一个线程。

您可以发布处理连接的代码吗?您描述的场景可能很好,但也取决于实现sd=socket(AF_INET,SOCK_STREAM,0);rc=bind(sd,(struct sockaddr_in*)和groupSock,sizeof(struct sockaddr_in));rc=监听(sd,100);对于(;count