简体   繁体   English

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

[英]C socket programming: calling recv() changes my socket file descriptor?

Hey all, I have this strange problem with recv(). 嘿所有,我有recv()这个奇怪的问题。 I'm programming client/server where client send() a message (a structure to be exact) and server recv() it. 我正在编程客户端/服务器,其中客户端发送()消息(结构准确)和服务器recv()它。 I am also working with multiple sockets and select(). 我也在使用多个套接字和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. read_set的问题是在read_set ,0~3没有设置,4是。 That is fine. 那样就好。 But when i call recv() , i suddently becomes 0. Why is that? 但是当我打电话给recv()i突然变成了0.为什么会这样? It doesn't make sense to me why recv() would take an socket file descriptor number and modify to another number. 对我来说,为什么recv()会获取套接字文件描述符号并修改为另一个数字是没有意义的。 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. 这就是打印出来的东西。

recv cannot modify its first argument, since it is taken by value. recv无法修改其第一个参数,因为它是按值获取的。

You don't show where you've declared msg or i , but based on this line 您没有显示您声明msgi ,但是基于此行

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

Where you use the -> operator on msg , I assume it's probably like this: msg上使用->运算符的地方,我假设它可能是这样的:

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 . 请注意, msg 已经是指针,因此&msg指向指针的指针

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 . 那么这将完成是接收数据,并试图将其存储在地方, msg 指针本身,而不是地方, msg Typically, pointers are only 4 bytes long, so this will overflow the storage if you receive more than four bytes. 通常,指针只有4个字节长,因此如果您收到的字节数超过4个,这将溢出存储空间。 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. 如果在msg之后在堆栈上声明了i ,则很可能它被此溢出覆盖,并且它恰好被接收到的数据包中的所有零字节覆盖。

Since msg is already a pointer, change your receive line to eliminate the superfluous indirection: 由于msg已经是指针,因此请更改接收行以消除多余的间接:

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. 如果handle_request函数实际上并不期望指向指针。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM