最大化C中套接字recv的char连接操作的效率

时间:2015-02-19 21:01:40

标签: c sockets recv strcat

我尝试在从缓冲区获取数据时充分利用效率,从套接字接收并将其复制到全局字符数组xmlResponce[35000]

    char buf[2048];
    if (sendResponce != -1)
    {
        int bytes;
        memset(buf, '\0', 2048);
        while((bytes = recv(sockfd, buf, 2047, 0)) > 0)
        {
            buf[bytes] = '\0';
            strcat(xmlResponce, buf);
        }
    }

我特别关注最小化内存碎片,因为我在Linux Kernel 2.6.27上有一些问题。有没有更有效的方法来做到这一点?使用strcat正确选择从缓冲区复制到主char数组吗?

2 个答案:

答案 0 :(得分:2)

首先,我认为你可能会过度思考这一点。内核内存碎片(如您对内核的引用所示)是物理RAM的碎片,这意味着伙伴算法无法分配物理上连续的页面。但是,由于你的记忆是虚拟记忆,这并不重要,因为几乎连续的记忆并不需要在物理上连续。虚拟内存碎片取决于您在用户空间(libc或其他)中分配页面的方式。

如果您真的关心虚拟内存碎片,请使用mmap( ... MAP_ANON ... )分配大型数组。使它变得比你可能需要的大(它实际上消耗了物理内存,直到你写入或读取每个页面),然后mremap如果你需要扩展它,它的大小是它的两倍。如果您查看man mallopt(特别是M_MMAP_THRESHOLD),您会看到如果您将原始分配足够大,malloc()将为您完成所有工作。所以我建议你只需要分配一个大缓冲区(如果你愿意,可以分配35000个字节),然后如果你要超支它,那么它的大小加倍。

现在,如何将字节写入缓冲区?

不要使用strcat。只需将它们直接写入缓冲区即可。根本不需要复制东西。这是一些未经测试的代码。

ssize_t offset = 0;

....

if (sendResponce != -1)
{
    ssize_t bytes;
    while((bytes = recv(sockfd, xmlResponse+offset, 65536, 0)) > 0)
    {
        offset += bytes;
    }
}

xmlResponse[offset] = 0;

注意,为了提高效率,我将recv的大小增加到65536字节。这通常意味着你通常会在一次通话中得到它。

不要忘记检查你是否在缓冲区末尾写字。为了清楚起见,我把它留了下来。

答案 1 :(得分:1)

除非你在代码中的某个地方进行malloc / realloc / free(看起来似乎不是这样),否则应该没有碎片问题。

主要问题是您的代码在接收数据的长度上是二次的,因为它在每个strcat上重新扫描xmlResponse。鉴于您已经知道长度

,Strcat不是最佳选择
if (sendResponce != -1)
{
    int bytes, offset = 0;
    while((bytes = recv(sockfd, buf, 2047, 0)) > 0 && 
           offset+bytes < sizeof(xmlResponce)-1)
    {
        memcpy(xmlResponce+offset, buf, bytes);
        offset+= bytes;
    }
    xmlResponse[offcet]=0;
}