c - 如何在流套接字字节流中查找特定字符串

标签 c

我是 C 的新手,在这里遇到了一些麻烦我试图解析一个 html 文件并计算文件中 p-tags 的数量。我正在使用不同大小的 block ,大小由用户输入。但是当大小跳到 200 时,我得到了错误的 p-tags 数量。我使用 recv 函数接收文件并使用缓冲区的内容来计算所述 p-tags。

    count = recv(s, buf, sizeof buf, 0);
    for(int i=0; i<chunk; i++)
    {
        if(buf[i]=='<')
          if(buf[i+1]=='p')
                if(buf[i+2]=='>')
                pcount++;>*/
    }

当 block 大小为 200 时,它应该返回 13 个 p-tags 但它返回了 15。

最佳答案

有几个问题。大概是chunk是缓冲区的大小。现在,如果 recv成功它将返回接收到的字节数。您应该使用 this 计数而不是 chunk用于限制循环。否则你会为失败的 recv 运行循环操作,它会计算缓冲区中存在的任何垃圾。

第二个问题当然是 <p>标记实际上可能位于 2 个 block 的边界上。

第三个是您可能越界读取缓冲区 - 即使 buf[i]有效并不意味着 buf[i + 2]是。


最简单,但也许不是最正确的解决方案是使用 fdopen在 socket 上,然后是 fgetc() ,或将整个主体读入缓冲区。让我们使用 fdopen虽然:

FILE *f = fdopen(s, "r+b");
size_t pcount = 0;

int c = 0;
while (c != EOF)
{
    if ((c = fgetc(f)) == '<' 
         && (c = fgetc(f)) == 'p'
         && (c = fgetc(f)) == '>') 
    {
        pcount += 1;
    }
}

这里我们将套接字包装成一个 <stdio.h> FILE ; fgetc返回文件中的下一个字符和 &&短路;最后一个的返回值fgetcc 中捕获还有;如果返回值为 EOF循环被打破并且pcount将包含正确的标签计数。

如果您不能使用 fdopen , 那么你可以为套接字编写自己的缓冲逻辑,甚至可以制作一个调用 recv 的模拟函数。一次一个字节...


或者你可以使用状态机:

int pstate = 0;

ssize_t count = recv(s, buf, sizeof buf, 0);
// TODO: add error checking...

for (ssize_t i = 0; i < count; i++)
{
    if (buf[i] == '<') {
        pstate = 1;
    }
    else if (pstate == 1 && buf[i] == 'p') {
        pstate = 2;
    }
    else if (pstate == 2 && buf[i] == '>') {
        pcount += 1;
        pstate = 0;
    }
    else {
        // if any other character is found,
        // or any of these characters was in wrong position
        // then reset the state
        pstate = 0;
    }
}

这将在不同的 block 大小上正常工作,并且不会解决缓冲区越界的问题。不过,作为一个并发症,它看起来确实比 fdopen 复杂得多。一个,即使它仍然缺少外循环!

关于c - 如何在流套接字字节流中查找特定字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54741715/

相关文章:

c - 以下程序中 "fflush(stdin)"的确切含义是什么?

c - 使用 poll() 检查文件修改

c - VS2013中一条语句中多个指针增量的解决方法

c - SSE 中的乘减法

c - 如何测量 FreeRTOS 中的执行时间?

字符 ch[] ="some string";

c - 有没有办法在 GCC 中使用 fopen_s() 或至少创建一个关于它的#define?

c - 使用从 recv() tcpServer c 接收的缓冲区的段错误

c - 如何在 C 中通过重复生成所有可能的变化

c++ - 将数字包装在结构中以避免隐式转换的优缺点