C套接字编程:调用recv()会更改我的套接字文件描述符?

3

大家好,我在使用recv()函数时遇到了一些奇怪的问题。我正在编写一个客户端/服务器程序,其中客户端发送消息(确切地说是一个结构体),而服务器则接收该消息。同时,我还在使用多个套接字和select()函数。

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

recv无法修改其第一个参数,因为它是按值传递的。

您没有展示您在哪里声明了msgi,但基于此行:

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个字节长,因此如果接收到超过四个字节的数据,则会导致存储溢出。如果imsg之后在堆栈上声明,则很可能被此溢出覆盖,并且它恰好被来自接收到的数据包的所有零字节所覆盖。
由于msg已经是一个指针,因此请更改接收行以消除多余的间接性。
num_bytes = recv(i, msg, MAX_MSG_BYTE, 0);

同样地,您可能想考虑对该行进行相同的更改。
handle_request(arg, &msg)

如果handle_request函数并不真正需要一个指向指针的参数。

这似乎很可能是问题所在。 - caf

1

我的第一个猜测是 sizeof(msg) < MAX_MSG_BYTE,当 recv 溢出 msg 时,它会破坏 i


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接