我如何使用memcpy()函数?

时间:2012-03-27 00:47:59

标签: c sockets

我正在尝试使用memcpy()函数将从read()获得的一些二进制数据存储到我的缓冲区中。

基本上,我想在我的缓冲区中存储buf:

#define MAX_BUFFER_SIZE 256
//...
char *
httpget(const char * domain, const int port, const char * headers)
{
    int sockfd;
    int buf_size = MAX_BUFFER_SIZE;

    struct sockaddr_in  sock_addr; 
    struct hostent  *   host;

    char * buffer;
    char * newbuf;
    char * tbuf;

    sockfd = socket(AF_INET,SOCK_STREAM,0);

    if( sockfd == -1 )
    {
        return NULL;
    }

    host = gethostbyname(domain);

    if( NULL == host )
    {
        close(sockfd);
        return NULL;
    }

    memset(&sock_addr, '\0', sizeof(sock_addr));
    sock_addr.sin_family = AF_INET;
    memcpy( &sock_addr.sin_addr.s_addr,
            host -> h_addr,
            host -> h_length );

    sock_addr.sin_port = htons(port);

    if( connect(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) == -1)
    {
        close(sockfd);
        return NULL;
    }

    if( write(sockfd, headers, strlen(headers) + 1) == -1)
    {
        close(sockfd);
        return NULL;
    }

    buffer = malloc( MAX_BUFFER_SIZE );
    tbuf = malloc( MAX_BUFFER_SIZE );

    if(buffer == NULL || tbuf == NULL)
    {
        return NULL;
    }

    int bytesloaded = 0;
    int readed;

    while( (readed = read(sockfd, tbuf, MAX_BUFFER_SIZE)) > 0 )
    {   
        if(bytesloaded + readed >= buf_size)
        {
            buf_size = buf_size + MAX_BUFFER_SIZE;  
            newbuf = realloc(buffer, buf_size);

            if(newbuf != NULL)
            {
                buffer = newbuf; 
            }
            else 
            {
                return NULL;
            }
        }

        memcpy(buffer, tbuf, readed);
        bytesloaded += readed;
    }

    close(sockfd);
    printf("buffer = %s", buffer);
    return buffer;
}

但是当我printf(“%s”,缓冲区)时;我只获得了具有7007内容长度的二进制的HTTP标头和�PNG字符。怎么解决这个问题?我希望这对你来说很清楚。任何帮助都非常感谢。谢谢。

3 个答案:

答案 0 :(得分:3)

我想你想要:

memcpy(buffer + bytesloaded, buf, readed);

当您尝试使用printf("%s",buffer)转储时,您没有看到整个响应,因为响应中发送的.png图像是可能包含空'\0'的二进制数据字节,printf()将在此时停止。

您有各种其他选项来检查响应中返回的数据(或有关它的信息):查看调试器中的buffer,转储bytesloaded变量,转储{{1}使用一个函数将其转换为十六进制显示,和/或将响应体(在标题和标题后面的CR / LF之后)写入buffer文件并在某事物中查看它这将显示图像。

答案 1 :(得分:1)

memcpy中有一个拼写错误,指的是buffe而不是缓冲区,虽然它可能只出现在帖子而不是你的实际代码中(我不相信它会用它编译)如果它是那肯定是问题所在。

更新:虽然其他答案表明可能存在空字节,但是在png头规范中没有位置,空字节应该是标题的一部分,所以唯一的位置可能是正文,但是因为你没有数据然后唯一的选择可能是,如果它是身体中的第一件事我认为真的是一个后壳,所以你可能尝试使用不同的信息来源,如另一个图像或其他网址,如果问题坚持所有的png图像然后它是printf和标题之间的东西(因此如果它在标题中有一个空字节,那么无论如何它都值得入侵)。

但请注意,在字母PNG出现CRLF然后出现EOF之后,虽然如果printf会出现问题会很有趣,但如果这是问题,那么转储到文件也不一定是解决方案除非你用png查看器打开它。

实际上你没有包含你的套接字源代码,因此如果是你自己编写的代码,请确保它不会在第一个EOF上停止,因为它是png头的一部分。

答案 2 :(得分:1)

由于printf(3)格式化指令%s将字节作为字符打印,直到遇到ASCII NUL字符。 PNG format可能允许NUL或者第9个字节 - 前8个字节是0x89PNG,然后是一些空白字符到发现特定种类的白色空间修剪。

我建议使用不同的printf(3)格式说明符来查看相关数据 - 或将其写入调试文件,以便您可以使用常用的十六进制编辑器对其进行编辑以验证其内容。