Программирование сокетов C: вызов recv () меняет дескриптор моего файла сокетов? - PullRequest
3 голосов
/ 20 апреля 2010

Привет всем, у меня странная проблема с recv (). Я программирую клиент / сервер, где клиент посылает () сообщение (точная структура) и сервер recv (). Я также работаю с несколькими сокетами и выберите ().

while(1)
{
    readset = info->read_set;
    info->copy_set = info->read_set;

    timeout.tv_sec = 1; 
    timeout.tv_usec = 0; // 0.5 seconds

    ready = select(info->max_fd+1, &readset, NULL, NULL, &timeout);

    if (ready == -1)
    {
        printf("S: ERROR: select(): %s\nEXITING...", strerror(errno));
        exit(1);
    }
    else if (ready == 0)
    {
        continue;
    }
    else
    {
        printf("S: oh finally you have contacted me!\n");
        for(i = 0; i < (info->max_fd+1); i++)
        {

            if(FD_ISSET(i, &readset)) //this is where problem begins
            {
                printf("S: %i is set\n", i);
                printf("S: we talking about socket %i son\n", i);  // i = 4
                num_bytes = recv(i, &msg, MAX_MSG_BYTE, 0);
                printf("S: number of bytes recieved in socket %i is %i\n", i, num_bytes); // prints out i = 0 what??

                if (num_bytes == 0)
                {
                    printf("S: socket has been closed\n");
                    break;
                }
                else if (num_bytes == -1)
                {
                    printf("S: ERROR recv: %d %s \n", i, strerror(errno));
                    continue;
                }
                else                    
                {
                    handle_request(arg, &msg);
                    printf("S: msg says %s\n", msg->_payload);
                }
            } // if (FD_ISSET(i, &readset)
            else
                printf("S:  %i is not set\n", i);
        } // for (i = 0; i < maxfd+1; i++) to check sockets for msg
    } // if (ready == -1)   

    info->read_set = info->copy_set;
    printf("S: copied\n");

} 

У меня проблема в том, что в read_set 0 ~ 3 не установлены, а 4 -. Это хорошо. Но когда я звоню recv(), i внезапно становится 0. Почему это? Мне не имеет смысла, почему recv() берет номер дескриптора файла сокета и изменяет его на другой номер. Это нормально? Я что-то упустил?

S:  0 is not set
S:  1 is not set
S:  2 is not set
S:  3 is not set
S: 4 is set
S: we talking about socket 4 son
S: i is strangely or unstrangely 0
S: number of bytes recieved in socket 0 is 40

Вот что он печатает.

Ответы [ 2 ]

2 голосов
/ 20 апреля 2010

recv не может изменить свой первый аргумент, поскольку он берется по значению.

Вы не показываете, где вы объявили msg или i, но на основе этой строки

printf("S: msg says %s\n", msg->_payload);

Где вы используете оператор -> на msg, я предполагаю, что это, вероятно, так:

struct somestruct* msg = malloc(sizeof(struct somestruct));
int i;

Тогда вы делаете это:

num_bytes = recv(i, &msg, MAX_MSG_BYTE, 0);

Обратите внимание, что msg является уже указателем, поэтому &msg является указателем на указатель .

Затем он получит данные и попытается сохранить их там, где находится указатель msg , а не в том месте, которое msg указывает на . Обычно указатели имеют длину всего 4 байта, поэтому это приведет к переполнению хранилища, если вы получите более четырех байтов. Если i объявлено в стеке после msg, то вполне вероятно, что оно перезаписывается этим переполнением, и происходит перезапись всех нулевых байтов из полученного пакета.

Поскольку msg уже является указателем, измените строку приема, чтобы устранить лишнюю косвенность:

num_bytes = recv(i, msg, MAX_MSG_BYTE, 0);

Аналогичным образом, вы можете рассмотреть возможность внесения того же изменения в строку

handle_request(arg, &msg)

, если функция handle_request действительно не ожидает указателя на указатель.

1 голос
/ 20 апреля 2010

Моим первым предположением было бы, что sizeof(msg) < MAX_MSG_BYTE, а когда recv переполняет msg, он сбрасывает i.

...