2010-04-20 169 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