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

时间:2015-08-01 16:20:33

标签: c windows sockets malloc realloc

我试图使用c获取我网站的源代码,我能够连接所有内容,但是当我实现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 :(得分:2)

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

要解决此问题,您可以通过更改

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

答案 1 :(得分:0)

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

Binary tides

虽然它使用linux的fcntl,但是等效的窗口是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;
}