代码之家  ›  专栏  ›  技术社区  ›  Hawk

通过动态分配空间在套接字上执行recv()

  •  0
  • Hawk  · 技术社区  · 9 年前

    我正在尝试使用c获取我的网站的源代码,我可以连接,但当我实现recv()代码时,它只接收源代码的最后几个字节。我想使用C函数动态分配缓冲区的空间以接收更多 malloc realloc .

    这是我目前掌握的代码:

    char *buffer = NULL;
    unsigned int i = 0;
    unsigned long LEN = 200;
    unsigned long cur_size = 0;
    
    buffer = (char*)malloc(sizeof(char)*LEN);
    do
    {
        if( status >= LEN )
        {
            cur_size += status;
            buffer = (char*)realloc(buffer, cur_size);
        }
        status = recv(cSocket, buffer, LEN, 0);
        if( status == 0 )
        {
            printf("Bye\n");
        }
        else if( status > 0 )
        {
            printf("%d\n", status);
        }
        else
        {
            printf("socket error=%d\n", WSAGetLastError());
            break;
        }
    }while( status > 0 );
    printf("%s\n", buffer);
    

    它仍然没有打印整个源代码。我该怎么办?

    伪代码:

    buffer = 'len chars';
    loop:
    if( status >= buffer ) buffer = 'resize to status chars';
    status = recv(sock, buffer, len, 0);
    end loop
    
    2 回复  |  直到 9 年前
        1
  •  3
  •   alk    5 年前

    当您提前调整缓冲区的大小时,这需要通过其大小来反映。当前是 本案。

    为了解决这个问题,例如,可以初始化 cur_size 具有 LEN 通过改变

    unsigned long cur_size = 0;
    

    unsigned long cur_size = LEN;
    

    假设有上述修复方法,您希望附加到缓冲区,而不是每次调用都覆盖它 recv() .

    为此,请更改此行

    status = recv(cSocket, buffer, LEN, 0);
    

    成为

    status = recv(cSocket, buffer + cur_size - LEN, LEN, 0);
    

    一种更直接的方法是不跟踪缓冲区的大小,而是跟踪接收的字节数,并始终以恒定的大小增加缓冲区。

    另外,分配内存的两个调用可以替换为一个:

    char *buffer = NULL;
    unsigned long LEN = 200;
    unsigned long bytes_received = 0;
    unsigned long cur_size = 0;
    int status = 0;
    
    do
    {
        if (bytes_received >= cur_size)
        {
            char * tmp;
            cur_size += LEN;
            tmp = realloc(buffer, cur_size);
            if (NULL == tmp)
            {
              fprintf(stderr, "realloc error=%d\n", WSAGetLastError());
              break;
            }
    
            buffer = tmp;
        }
    
        status = recv(cSocket, buffer + bytes_received, LEN, 0);
        if (status == 0)
        {
            printf("Bye\n");
        }
        else if (status > 0)
        {
          bytes_received += status;
          printf("%d\n", status);           
        }
        else /* < 0 */
        {
            fprintf(stderr, "socket error=%d\n", WSAGetLastError());
        }
    } while (status > 0);
    
    printf("%s\n", buffer);
    
        2
  •  0
  •   Hawk    9 年前

    经过一番研究,我找到了这个网站,终于找到了我想要的东西。

    Binary tides

    尽管它使用linux的 fcntl ,windows等效值为 ioctlsocket 其用于设置套接字的非阻塞模式。

    要查看确切的功能,请访问网站。我修改了版本并将套接字设置为阻塞模式。

    int total_recv(SOCKET s)
    {
        int size_recv = 0, total_size = 0, block = 00;
        char chunk[BUFLEN];
    
        ioctlsocket(s, FIONBIO, (unsigned long*)&block); // set mode to block
        // not necessary but clarification of function, mode is block by
        // default
    
        while( 1 )
        {
            memset(chunk, 0, BUFLEN);
            if( ( size_recv = recv(s, chunk, BUFLEN, 0) ) == SOCKET_ERROR )
            {
                printf("Error receiving\n");
            }
            else if( size_recv == 0 )
            {
                break;
            }
            else
            {
                total_size += size_recv;
    
                // i used file since console wouldn't show full source code
                FILE *fp = NULL;
                fp = fopen("source.txt", "a");
                fprintf(fp, chunk);
                fclose(fp);
            }
        }
    
        return total_size;
    }