C WINAPI recv() 在接收到所有数据之前返回 0

发布于 2024-12-20 12:22:00 字数 2119 浏览 1 评论 0原文

我正在使用 中的代码MSDN 的 recv() 页面,但我更改了发送的数据以及目标端口和 IP 地址,以发送 HTTP GET 请求来获取 google.com/index.php。每次我运行它时,recv() 在获取大部分页面后返回 0,但不是全部。我用wireshark验证了整个页面都已收到,但它在之后停止,后跟一个非ASCII符号。

这是我正在使用的代码,我删除了大部分注释和错误检查,但其他方面与上面的链接相同:

#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;
}

我正在使用 mingw32 版本 4.2.1 在 linux 上进行编译。

I'm using the code from MSDN's recv() page, but I changed the data being sent and destination port and IP address to send a HTTP GET request to get google.com/index.php. Every time I run it, recv() returns 0 after getting most of the page, but not all. I verified with wireshark that the entire page is received, but it stops after <a href=//google.co, followed by a non-ASCII symbol.

Here's the code I'm using, I took out most of the comments and error checking but otherwise it's the same as the link above:

#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;
}

I'm compiling on linux with mingw32 version 4.2.1.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白色秋天 2024-12-27 12:22:00

我只看了一眼,但最明显的错误是:

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

没有人会为你编写使 C 字符串起作用的 NUL 字符。特别是,由于打印字符串意味着搜索 NUL 字符,并且没有通过网络发送任何字符,因此在 recv 之后的最后一个 printf 也可能会吐出一些垃圾它位于上一次循环迭代的缓冲区中。你可以尝试这样的事情:

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

这样你就只打印 recv 告诉你在缓冲区中的字符。

I've only glanced, but the most glaring error is this:

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

Nobody will write that NUL character for you that makes C strings work. In particular, since printing strings means searching for NUL characters, and there aren't any sent over the wire, your last printf after a recv will likely also spit out some garbage that was in the buffer from the previous loop iteration. You can try something like this:

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

This way you only print characters that recv told you were in the buffer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文