首页 文章

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

提问于
浏览
-2

我'm trying to get the source code of my website using c, I'能够连接和一切,但是当我实现recv()代码时,它只接收源代码的最后几个字节 . 我想为缓冲区动态分配空间,以便使用C函数 mallocrealloc 接收更多空间 .

这是我到目前为止的代码:

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 回答

  • 0

    当您提前调整缓冲区大小时,需要通过其大小来反映 . 目前这是 not 的情况 .

    要解决此问题,您可以通过更改初始化 cur_sizeLEN

    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

    好吧,经过一番研究,我偶然发现了这个网站,终于找到了我想要的东西 .

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

相关问题