Сервер может принимать только n клиентов

Я программирую серверный код с использованием языка C, который должен принимать только несколько клиентов, и если появится дополнительный, сервер заставит этого клиента ждать, пока один из старых клиентов не прекратит работу.

Например (сервер может принимать только 10 клиентов, если новый клиент прибыл, сервер поставит этого клиента ждать, пока один из 10 клиентов не прекратит работу, после чего он может быть обслужен).

Я знаю, что должен использовать функцию signal() после функции listen() и перед accept() и создать значение, которое подсчитывает количество клиентов, но я не знаю, как правильно его использовать.

Может ли кто-нибудь дать мне подсказку или простой пример.

Спасибо,,,,,,


person Ali    schedule 14.11.2014    source источник
comment
Пробовали ли вы что-нибудь раньше...?   -  person Anbu.Sankar    schedule 14.11.2014
comment
поиск «многопоточности» и, в частности, pthreads   -  person jev    schedule 14.11.2014
comment
put that client to wait ... как? что именно здесь обозначено как wait?   -  person Sourav Ghosh    schedule 14.11.2014
comment
@SouravGhosh Сервер заблокирует этого клиента   -  person Ali    schedule 14.11.2014
comment
@Али еще раз, как block ? отклонять? тогда вы можете использовать backlog в listen() для достижения этого. см. справочную страницу.   -  person Sourav Ghosh    schedule 14.11.2014
comment
@SouravGhosh, я использовал его. Я установил отставание на 2, затем «слушаю (listenfd, отставание)». Но когда я подключаю более 2 клиентов, ничего не происходит. Клиент может подключиться к серверу, даже если клиент номер 3   -  person Ali    schedule 14.11.2014


Ответы (1)


Нет необходимости использовать signal(). Пример:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

main()
{
    int s = socket(PF_INET, SOCK_STREAM, 0);    // server socket
    if (s            == -1) return perror("socket"), 1;
    if (listen(s, 0) == -1) return perror("listen"), 1;
    const int n = 10;   // number of clients allowed to be served
    fd_set fds, rfds;
    FD_ZERO(&fds);
    FD_SET(s, &fds);    // initially, set of sockets holds server
    int nfds = s+1, fd, clients = 0;
    while (rfds = fds, select(nfds, &rfds, NULL, NULL, NULL) > 0)
        for (fd = 0; fd < nfds; ++fd)
            if (FD_ISSET(fd, &rfds))    // see which sockets of set are ready
                if (fd == s)            // is it the server socket?
                {   // yes, so it is a client's connection request
                    printf("new client request ");
                    struct sockaddr_in sa = { AF_INET, 0, INADDR_ANY };
                    socklen_t sal = sizeof sa;
                    int c = accept(s, (struct sockaddr *)&sa, &sal);
                    if (c == -1) return perror("accept"), 1;
                    FD_SET(c, &fds); if (nfds <= c) nfds = c+1; // add client
                    printf("accepted (fd=%d) # clients now %d\n", c, ++clients);
                    if (clients == n)   // allowed number hit?
                        puts("Further client requests will be ignored."),
                        FD_CLR(s, &fds);    // don't watch server now
                }
                else
                {   // this is a client's message or termination
                    printf("client fd=%d: ", fd);
                    char buf[BUFSIZ];
                    size_t count = read(fd, buf, sizeof buf);
                    if (count > 0) fwrite(buf, 1, count, stdout);
                    else
                    {   // no more data from client, so close the connection
                        close(fd);
                        FD_CLR(fd, &fds);   // remove client from watch set
                        printf("closed, # clients now %d\n", --clients);
                        if (clients == n-1) // went just below allowed number?
                            FD_SET(s, &fds),    // watch server again
                            puts("New client requests will be accepted again.");
                    }
                }
    return perror("select"), 1;
}

Примечание: эта программа привязывается к произвольному свободному порту, который вы можете узнать с помощью e. грамм. netstat -tlp. Конечно, вы также можете bind() на определенный адрес и порт. В любом случае вы можете проверить это с e. грамм. nc hostname port.

person Armali    schedule 03.07.2015