Recv вмешивается в recvfrom внутри того же оператора select в C - PullRequest
0 голосов
/ 30 мая 2020

Я пытаюсь создать выбранный сервер, который может обрабатывать соединения как TCP, так и UDP, но когда я пытаюсь получить сообщение UDP, наличие моего recv не позволяет коду достичь recvfrom. Я все еще могу получить сообщение UDP, если отправлю его дважды (не знаю почему). Как я могу изменить это, чтобы правильно получать от tcpfd на recv и udpfd на recvfrom (это единственные два читаемых fd, которые когда-либо будут в главном наборе чтения)?
UDP-сообщение отправляется с идентичного сервера на тот же компьютер (и отправляется правильно), и оба сокета, которые я использую, были правильно настроены. Recvfrom работает правильно, если я удалю оператор recv if. Код основан на https://www.gnu.org/software/libc/manual/html_node/Server-Example.html#Server -Пример

while (1)
{
    //masterset is contains 'tcpfd' and 'udpfd' for the tcp and udp socket I want to listen to
    readset = master;  

    if (select(FD_SETSIZE, &readset, NULL, NULL, NULL) >= 0)
    {
        for (int i = 0; i <= FD_SETSIZE; i++)
        {
            len = sizeof servaddr;

            if (FD_ISSET(i, &readset))
            {

                if (i == tcpfd)
                {
                    int new;
                    new = accept(tcpfd, (struct sockaddr *)&servaddr, &len);
                    if (new < 0)
                    {
                        perror("accept");
                        exit(EXIT_FAILURE);
                    }
                    else
                    {
                        FD_SET(new, &masterset);
                    }
                }

                else if ((i != udpfd) && ((nbytes = recv(i, buffer, sizeof(buffer), 0)) > 0))
                {

                }

                else if ((i == udpfd) && (nbytes = recvfrom(udpfd, buffer, sizeof(buffer), 0, 
                (struct sockaddr *)&servaddr, &len)) > 0)
                {

                }
            }
        }
    }

1 Ответ

2 голосов
/ 30 мая 2020

Есть несколько проблем с вашим кодом, но, скорее всего, проблема заключается в том, что select изменяет наборы, которые вы ему передаете.

Это означает, что readset в нем есть два набора дескрипторов, но только один доступен для чтения, тогда второй будет удален из набора.

Вам необходимо сбросить наборы, которые вы передаете в select перед следующим вызовом в l oop . Я предполагаю, что это то, для чего предполагается использовать masterset, но вы забыли его использовать.


Что касается других проблем, наиболее серьезной из них является l oop condition i <= FD_SETSIZE . Наборы дескрипторов на самом деле являются массивами, и ваш l oop приведет к ошибке «off-by-one» и индексации за пределами массива. Это, конечно, приводит к неопределенному поведению .

...