以下STCP代码片段展示了我观察到的问题。它会在recv调用处阻塞,直到有数据可读取,随后处理接收到的数据并再次调用recv——该调用要么返回更多数据(或报错),要么再次阻塞。若发生错误,recv将返回-1,并将错误代码设置在errno变量中。您认为这段代码是否正确?
while (1)
{
cBytes = recv (socks1, buffer, BUFFERLEN, 0);
if (cBytes == -1)
{
perror ("Unexpected error at recv");
exit (errno);
}
else
printf ("number of bytes received : %dn", cBytes);
}
|
该代码假设远程对等方永远不会优雅地关闭连接。当远程对等方执行优雅关闭(即调用close或shutdown函数)时,recv会通过返回零字节向本地应用程序发出提示。后续对recv的调用将持续返回零字节。结果导致代码陷入无所作为的紧循环。例如:
接收字节数:8 接收字节数:57 接收字节数:16 接收字节数:1 接收字节数:1 接收字节数:0 接收字节数:0 接收字节数:0 接收字节数:0 接收字节数:0. . . . . |
即使应用协议规定远程对等方永远不会优雅地关闭连接,你也无法保证连接永远不会被优雅关闭。远程应用程序可能存在缺陷,或者当应用进程终止时,远程TCP堆栈可能会执行优雅关闭。又或者,其他应用程序建立了连接,但在未收到预期响应时将其关闭。 安全审计(或恶意用户)执行端口扫描或抓取系统标识时,也可能执行优雅关闭。关键在于:你必须始终处理零字节的情况。
while (1)
{
cBytes = recv (socks1, buffer, BUFFERLEN, 0);
if (cBytes <= 0)
{
if (cBytes < 0)
{
perror ("Unexpected error at recv");
exit (errno);
}
else
{
printf ("received closen");
close (socks1);
exit (0);
}
}
else
printf ("number of bytes received : %dn", cBytes);
}
|
接收字节数:28 接收字节数:2 接收字节数:58 接收关闭 |
