使用 select() 监听多个客户端 (TCP) [英] using select() to listen to multiple clients (TCP)

查看:52
本文介绍了使用 select() 监听多个客户端 (TCP)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了 (TCP) 服务器来监听客户端并与之交互.现在我正在尝试调整该服务器代码以收听多个客户端.我想使用 select,但我对找到的一些示例和解释感到困惑.

I have developed (TCP) server to listen to a client and interact with it. Now I'm trying to adapt that server code to listen to mulitple clients. I am wanting to use select, but I'm getting confused with some of the examples and explainations I've found.

我一直在阅读:http://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htmhttp://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htm 已经向我推荐了这两个..:S

I have been reading: http://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htm and http://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htm both of which have been recommended to me.. :S

第一个站点的示例似乎不那么复杂..(虽然仍然不知道如何将它调整到我的代码中,因为我对网络等非常非常陌生)但我担心我错过了关键方面由于第二个站点示例的复杂性.

The first site's example seems less complex.. (though still don't know how to adapt it to my code as I am very very very new to network etc.) but I worry that I'm missing out on key aspects due to the complexity of the second site's example.

下面是我的服务器代码的快照,只监听一个客户端(包含一些伪代码以减少不那么重要的东西):

Below is kind of a snapshot of my server code when only listening for one client (some psuedocode included to minimize not so important stuff):

int main(int argc, char *argv[])
{
    int    sockfd, newsockfd, portno, clilen;
    char   buffer[3];
    struct sockaddr_in serv_addr, cli_addr;
    int    n;

    if (argc < 2)
    {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
    }

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0){error("ERROR opening socket");}

    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno                    = atoi(argv[1]);
    serv_addr.sin_family      = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port        = htons(portno);


    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
        {error("ERROR on binding");}

    listen(sockfd,5);

    clilen = sizeof(cli_addr);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

    if (newsockfd < 0){error("ERROR on accept");}


    while (UNTIL END OF FILE)
    {
        <DO SOME FILE READING STUFF>

        n = write(newsockfd, "test/n", 5);

        if (n < 0){error("ERROR writing to socket");}


        bzero(buffer,3);
        n = read(newsockfd,buffer,3);

        if (n < 0){error("ERROR reading from socket");}

        buffer[n] = 0;

        <DO SOME STRING STUFF>

        while(done != 1)
        {
            bzero(buffer,3);
            n = read(newsockfd,buffer,3);

            if (n < 0){error("ERROR reading from socket");}

            buffer[n] = 0;    

            if(strcmp(buffer, "CO"))
            {
                done = 1;
            }
        }

        done = 0;
    }

    <DO STUFF>


    n = write(newsockfd, "DN\n", 2);

    if (n < 0){error("ERROR writing to socket");}

    close(sockfd);
    close(newsockfd);

    return 0;   

}

哪个站点的 select() 示例最适合我正在尝试做的事情(更改服务器代码以侦听多个客户端)?有人可以用更简单的术语为我解释 select() 吗?(因为我对这一切都很陌生......)

Which site's example for select() would work best for my what I'm trying to do (change the server code to listen to multiple clients)? Could someone explain select() in some more simplier terms for me? (since I'm so new to this and all...)

谢谢!

推荐答案

您需要在 accept() 和以下代码周围环绕一个循环,以便您可以接受多个连接程序的生命.然后您需要决定您的服务器将如何处理多个连接.您有几个选择:

You need to wrap a loop around the accept() and following code, so that you can accept more than one connection over the life of the program. You then need to decide how your server is going to handle multiple connections. You have a few choices:

  • 使用多个线程,每个客户端一个线程.
  • 使用分叉服务器,每个客户端一个进程.
  • 使用单个服务器,它将使用 select() 来决定哪些文件描述符已准备就绪.
  • Use multiple threads, one thread per client.
  • Use a forking server, one process per client.
  • Use a single server, which will use select() to decide which file descriptor(s) are ready.

在前两种情况下,子线程或进程一心一意地处理一个客户端;它会等待,而客户端正在研究如何响应它发送的内容,这意味着其他线程或进程在 CPU 上轮流使用.主题有多种变体,可以预先启动一定数量的工作线程或进程并安排它们来处理工作量,但这更复杂.

In the first two cases, the child thread or process is single-mindedly dealing with one client; it will wait while the client is working out how to respond to what it sends, which means that other threads or processes get a turn at the CPU. There are variations on the theme that prelaunch some number of worker threads or processes and arrange for those to pick up the workload, but that's more complex.

在最后一种情况下,您将设置您希望 select() 处理的文件描述符数组,然后将该列表的副本传递给 select() (因为它踩遍了它).当您有工作要做时(因为 select() 返回),如果准备就绪,您可以对正在侦听的文件描述符执行 accept(),或者你从已经打开的套接字描述符中读取,如果它们准备好了.

In the last case, you'll set up an array of the file descriptors you want select() to work on, and then pass a copy of that list to select() (since it tramples all over it). When you've got work to do (because select() returns), you perform an accept() on the file descriptor that you're listening on if that's ready, or you read from the already opened socket descriptors if they're ready.

这篇关于使用 select() 监听多个客户端 (TCP)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆