2013-04-16 163 views
0

我試圖做一個異步UDP聊天應用程序,目前只有一個客戶端和服務器。異步udp服務器客戶端應用程序

當我運行我的服務器時,會顯示大量冗餘數據。之後,當輸入一些文本時,

發送文件時出錯!

被顯示。

有人可以看看代碼,讓我知道我要去哪裏錯了嗎?

服務器:
u_long iMode = 1; ioctlsocket(sd,FIONBIO,& iMode); int n = sd + 1;

fd_set readfds,writefds; 
while(1) 
{ 
    FD_ZERO(&readfds); 
    FD_ZERO(&writefds); 
    FD_SET(sd,&readfds); 
    FD_SET(sd,&writefds); 

    int rv = select(n, &readfds, &writefds, NULL, NULL); 
    if(rv==-1) 
    { 
     printf("Error in Select!!!\n"); 
     exit(0); 
    } 
    if(rv==0) 
    { 
     printf("Timeout occurred\n"); 
    } 
    if (FD_ISSET(sd, &readfds)) 
    { 
     FD_CLR(sd,&readfds); 
     int client_length = (int)sizeof(struct sockaddr_in); 
     memset(&buffer,0,sizeof(buffer)); 
     int bytes_received = recvfrom(sd, buffer,SIZE, 0, (struct sockaddr *)&client, &client_length); 
     if (bytes_received < 0) 
     { 
      fprintf(stderr, "Could not receive datagram.\n"); 
      closesocket(sd); 
      WSACleanup(); 
      exit(0); 
     } 
    } 

    printf("\nClient says: %s",buffer); 
    printf("\nWrite :"); 

    fgets(buffer,SIZE,stdin); 
    if(FD_ISSET(sd,&writefds)) 
    { 
     FD_CLR(sd,&writefds); 
     int client_length = (int)sizeof(struct sockaddr_in); 
     if(sendto(sd, buffer,strlen(buffer), 0, (struct sockaddr *) &client,client_length)<0) 
     { 
      printf("Error sending the file! \n"); 
      exit(1); 
     } 
    } 
} 
closesocket(sd); 
WSACleanup(); 

return 0; 
} 
+0

首先,您不需要手動清除套接字(例如'FD_CLR'調用)。無論如何,在選擇電話之前,您都要重置電話簿。 –

+0

其次,在memset調用中不要使用'&buffer'。如果'buffer'是一個指針,它就不會做它認爲它做的事情。另外,如果'buffer'是一個指針,那麼'sizeof(buffer)'將返回_pointer_的大小,而不是它指向的大小。 –

+0

WSAGetLastError在失敗的sendto調用之後返回什麼? – selbie

回答

1

我看到一個問題。此行:

int rv = select(n, &readfds, &writefds, NULL, NULL); 

幾乎總是會立即返回readfds爲空。但writefds將幾乎ALWAYS設置爲「sd」套接字表明它已準備好寫入/發送。

因此,您的代碼正確地跳過了嘗試調用recvfrom(),但沒有阻止它落入發送代碼路徑。所有的變量,如客戶端,客戶端長度和緩衝區可能在那時都未初始化。或者更糟糕的是,緩衝區和客戶端正是它們在循環中最後成功調用的內容。這可能解釋了冗餘數據。

我的建議是根本沒有在select調用中設置「writefds」。然後只有在你真正閱讀時才發送。無論如何sendto通話不會阻塞任何大量時間。

+0

@ selbie,所以我應該調用select()for只讀? –

+0

@AaymanKhalid - 是的。 – selbie

+0

@ selbie,對不起,它確實刪除了服務器上的冗餘數據,但並沒有解決我的問題:( –