2011-12-11 24 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