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

发布于 2024-08-29 03:50:21 字数 2327 浏览 4 评论 0原文

大家好,我在使用recv()时遇到了这个奇怪的问题。我正在对客户端/服务器进行编程,其中客户端 send() 一条消息(确切地说是一个结构),服务器 receive() 消息。我还使用多个套接字和 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

这就是它打印出来的内容。

Hey all, I have this strange problem with recv(). I'm programming client/server where client send() a message (a structure to be exact) and server recv() it. I am also working with multiple sockets and 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");

} 

the problem I have is that in read_set, 0~3 aren't set and 4 is. That is fine. But when i call recv(), i suddently becomes 0. Why is that? It doesn't make sense to me why recv() would take an socket file descriptor number and modify to another number. Is that normal? Am I missing something?

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

That's what it prints out.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

护你周全 2024-09-05 03:50:21

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

您不会显示声明 msgi 的位置,而是基于此行在

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

< 上使用 -> 运算符的位置code>msg,我假设它可能是这样的:

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

然后你这样做:

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

注意 msg 已经是一个指针,所以 &msg< /code> 是指向指针的指针

接下来要做的就是接收数据并尝试将其存储在 msg pointer 本身所在的位置,而不是 msg 指向的位置。通常,指针只有 4 个字节长,因此如果接收超过 4 个字节,就会导致存储溢出。如果 imsg 之后在堆栈上声明,那么它很可能被此溢出覆盖,并且它恰好被接收到的所有零字节覆盖包。

由于 msg 已经是一个指针,因此更改您的接收行以消除多余的间接:

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

您可能需要考虑对该行进行相同的更改

handle_request(arg, &msg)

同样,如果 handle_request 函数是, 并不真正期待指针到指针。

recv cannot modify its first argument, since it is taken by value.

You don't show where you've declared msg or i, but based on this line

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

Where you use the -> operator on msg, I assume it's probably like this:

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

Then you do this:

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

Note that msg is already a pointer, so &msg is a pointer to the pointer.

What this will then do is receive data and try to store it in the place where the msg pointer itself is, not the place that msg points to. Typically, pointers are only 4 bytes long, so this will overflow the storage if you receive more than four bytes. If i is declared on the stack after msg, then it is likely that it is being overwritten by this overflow, and it happens to get overwritten by all zero bytes from the received packet.

Since msg is already a pointer, change your receive line to eliminate the superfluous indirection:

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

Similarly, you may want to consider making the same change to the line

handle_request(arg, &msg)

if the handle_request function is not really expecting a pointer-to-pointer.

你穿错了嫁妆 2024-09-05 03:50:21

我的第一个猜测是 sizeof(msg) sizeof(msg) sizeof(msg) sizeof(msg) < MAX_MSG_BYTE 并且当 recv 溢出 msg 时,它会丢弃 i

My first guess would be that sizeof(msg) < MAX_MSG_BYTE and when recv overflows msg it trashes i.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文