2011-12-11 23 views
0

我使用的代碼來自MSDN's recv() page,但我更改了要發送的數據以及目標端口和IP地址,以發送HTTP GET請求以獲取google.com/index .PHP。每次運行它時,recv()在獲得大部分頁面後返回0,但不是全部。我用wireshark驗證整個頁面已收到,但它在<a href=//google.co之後停止,後面跟着一個非ASCII符號。C WINAPI recv()在收到所有數據之前返回0

下面是我使用的代碼,我拿出大部分的意見和錯誤檢查,但否則它與上面相同的鏈接:

#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <stdio.h> 

int main() { 
    WSADATA wsaData; 
    int iResult; 

    SOCKET ConnectSocket = INVALID_SOCKET; 
    struct sockaddr_in clientService; 

    char *sendbuf = "GET /index.php\r\nHost: www.google.com\r\n\r\n"; 
    char recvbuf[512]; 
    int recvbuflen = 512; 

    iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 

    clientService.sin_family = AF_INET; 
    clientService.sin_addr.s_addr = inet_addr("74.125.224.180"); 
    clientService.sin_port = htons(80); 

    iResult = connect(ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService)); 

    iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0); 

    printf("Bytes Sent: %ld\n", iResult); 

    // shutdown the connection since no more data will be sent 
    iResult = shutdown(ConnectSocket, SD_SEND); 
    if (iResult == SOCKET_ERROR) { 
     printf("shutdown failed: %d\n", WSAGetLastError()); 
     closesocket(ConnectSocket); 
     WSACleanup(); 
     return 1; 
    } 

    // Receive until the peer closes the connection 
    do { 

     iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); 
     if (iResult > 0){ 
      printf("%512s", recvbuf); 
      //printf("recv returned %d... got %d bytes\n", iResult, recvbuflen); 
     } 
     else if (iResult == 0) 
      printf("\n\nConnection closed\n"); 
     else 
      printf("\n\nrecv failed: %d\n", WSAGetLastError()); 

    } while(iResult > 0); 

    // cleanup 
    closesocket(ConnectSocket); 
    WSACleanup(); 

    return 0; 
} 

我編譯的Linux上4.2的mingw32版本。 1。

+0

Linux上的'WSACleanup()'? MSDN可能不是在Linux上學習Berkley套接字的最佳位置。嘗試http://beej.us/guide/bgnet –

+0

是什麼讓你認爲你可以在套接字的數據上使用'printf''%s'?它不是零終止的。 – asveikau

+0

我正在與Win32編譯器MingW交叉編譯。 printf%512s應該在到達緩衝區末尾之前停止。我知道它會在最後一次打印垃圾,但我正在尋找關閉標記,並且該頁面以標記結尾。 – user1091954

回答

0

我只掃了一眼,但最明顯的錯誤是這樣的:

if (iResult > 0){ 
     printf("%512s", recvbuf); 

沒有人會寫你NULL字符,使C字符串工作。特別是,由於打印字符串意味着搜索NUL字符,並且沒有任何通過線路發送,所以recv之後的最後一個printf也可能會從上一次循環迭代中吐出一些垃圾,該垃圾在緩衝區中。你可以嘗試這樣的事情:

if (iResult > 0) 
{ 
    char *p = recvbuf; 
    while (iResult--) 
     fputc(*p++, stdout); 
} 

這樣,你只打印字符recv告訴你是在緩衝區中。

+0

或者只是'printf(「%。* s」,iResult,recvbuf);' – Wiz

+0

格式化字符串「%512s」應該將損壞保持在最低限度,因爲緩衝區幾乎每次都是滿的,但是我試過了你的代碼,該程序在打印第一個緩衝區後返回,這是大部分頭文件和幾行html。我嘗試製作緩衝區爲32kb,並且只打印了幾行,仍然比我的原始代碼少得多。隨着更大的緩衝區和Wiz的代碼,我得到整個頁面。 – user1091954

+0

實際上,當它到達Wiz發佈的行時,它會崩潰。用'char fstr [128]; sprintf(fstr,「%%% ds」,iResult); printf(fstr,recvbuf);'它可以工作,但打印最後一位兩次。 – user1091954