【问题标题】:C socket programming: calling recv() changes my socket file descriptor?C 套接字编程:调用 recv() 会更改我的套接字文件描述符?
【发布时间】:2011-02-09 22:24:21
【问题描述】:

大家好,recv() 有一个奇怪的问题。我正在编写客户端/服务器,客户端发送()一条消息(确切地说是一个结构)和服务器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

就是这样打印出来的。

【问题讨论】:

    标签: c unix sockets client-server recv


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      您没有显示您声明msgi 的位置,而是基于这一行

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

      如果你在msg 上使用-&gt; 运算符,我认为它可能是这样的:

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

      然后你这样做:

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

      注意msg已经是一个指针,所以&amp;msg是一个指向指针的指针

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

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

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

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

      handle_request(arg, &msg)
      

      如果handle_request 函数并不真正期待指针。

      【讨论】:

      • 这似乎很可能是问题所在。
      猜你喜欢
      • 2012-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 2013-11-06
      相关资源
      最近更新 更多