C 如何在流套接字字节流中查找特定字符串
我是C新手,在这里遇到了一点小麻烦,我试图解析一个html文件,并计算文件中的p标记数。我使用不同大小的块,大小由用户输入。但是当尺寸跳到200时,我得到了错误数量的p标签。我使用recv函数来接收一个文件,并使用缓冲区的内容来计算所述p标签C 如何在流套接字字节流中查找特定字符串,c,C,我是C新手,在这里遇到了一点小麻烦,我试图解析一个html文件,并计算文件中的p标记数。我使用不同大小的块,大小由用户输入。但是当尺寸跳到200时,我得到了错误数量的p标签。我使用recv函数来接收一个文件,并使用缓冲区的内容来计算所述p标签 count = recv(s, buf, sizeof buf, 0); for(int i=0; i<chunk; i++) { if(buf[i]=='<') if(buf[i+1
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++;>*/
}
count=recv(s,buf,sizeof buf,0);
对于(int i=0;i*/
}
当区块大小为200时,它应该返回13个p标签,但它返回15个。有几个问题。推测
chunk
是缓冲区的大小。现在,如果recv
成功,它将返回接收的字节数。您应该使用此计数而不是chunk
来限制循环。否则,您将使用n即使是失败的recv
操作,它也会对缓冲区中存在的任何垃圾进行计数
当然,第二个问题是,
标记实际上可能位于两个块的边界上
第三个问题是,您可能正在读取超出边界的缓冲区-即使buf[i]
是有效的,但这并不意味着buf[i+2]
是有效的
最简单但可能不是最正确的解决方案是在套接字上使用
fdopen
,然后使用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;
}
}
这将在不同的块大小之间正常工作,并且不会解决缓冲区超出范围的问题。但是,与
fdopen
相比,它看起来要复杂得多,即使它仍然缺少外部循环!什么是chunk
?它与rec返回的count
有什么关系v
?当i
等于chunk-1
或chunk-2
时,索引i+1
和i+2
是否有效?请尝试创建一个适当的索引来显示给我们。另外,请阅读,以及。最后,请。在处理文件时,我必须以字节大小由通过命令行参数向用户发送消息。Count与程序的另一部分有关,在该部分中,我返回html文件中的字节数。如果Count
,会发生什么情况?如果使用TCP套接字,请记住没有消息边界或数据包。在单个recv
调用中接收的数据可能小于what是在一次send
调用中发送的,如果在调用recv
之前缓冲了两次或两次以上的send
调用,则发送的次数甚至更多。索引i+1
和i+2
将超出块大小的范围。而且您甚至似乎没有检查错误,这是套接字通信。@RaqueldeAnda如果您需要使用特定的块大小,那么状态机可能就是您应该使用的
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;
}
}