2010-04-20 167 views
3

嘿,我有recv()这个奇怪的问题。我正在编写客户端/服务器,客户端发送()一个消息(确切的结构)和服务器recv()它。我也在使用多个套接字和select()。C编程:调用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 

这就是它打印出来的。

回答

1

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

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个字节长,所以如果你收到4个以上的字节,这会使存储溢出。如果imsg之后在堆栈上声明,那么它很可能被该溢出覆盖,并且它恰好被接收到的数据包中的所有零字节覆盖。

由于msg已经是一个指针,改变你的接收线,以消除多余的间接:

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

同样的,你可能要考虑做同样的修改到行

handle_request(arg, &msg) 

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

+0

这似乎很可能是问题所在。 – caf 2010-04-20 00:56:58