Linux C++;引入ostringstream时,原始套接字嗅探器-recvfrom()失败 我用C++编写了一个包嗅探器,用流代替了代码> Primff()/Cux>来存储和创建输出。我遇到的问题是,当我有两个或多个使用流生成输出的语句时,recvfrom()似乎失败并返回-1

Linux C++;引入ostringstream时,原始套接字嗅探器-recvfrom()失败 我用C++编写了一个包嗅探器,用流代替了代码> Primff()/Cux>来存储和创建输出。我遇到的问题是,当我有两个或多个使用流生成输出的语句时,recvfrom()似乎失败并返回-1,c++,linux,packet-sniffers,raw-sockets,iomanip,C++,Linux,Packet Sniffers,Raw Sockets,Iomanip,如果我对两个输出生成语句中的一个进行注释,则程序运行正常。通过反复试验,我发现通过从std::cout语句中删除std::setw(),它将正常工作并显示数据包和“beef”消息 任何想法或帮助都将不胜感激,因为我不知所措,正在考虑恢复使用printf(),因为它从未出现过这个问题(而且比流更快)。我承认,这确实是我第一次使用ostringstream,而且我可能没有正确地使用它 我的简化源代码: #include <iostream> #include <sstream>

如果我对两个输出生成语句中的一个进行注释,则程序运行正常。通过反复试验,我发现通过从
std::cout
语句中删除
std::setw()
,它将正常工作并显示数据包和“beef”消息

任何想法或帮助都将不胜感激,因为我不知所措,正在考虑恢复使用
printf()
,因为它从未出现过这个问题(而且比流更快)。我承认,这确实是我第一次使用ostringstream,而且我可能没有正确地使用它

我的简化源代码

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <linux/if_packet.h>

std::string BufferInHex( unsigned char * buffer, int length )
{
    std::ostringstream out;
    for( int i = 0; i < length; i ++ ) {
        if( i % 16 == 0 && i != 0 ) {
            out << "\n";
        }
        else if( i % 8 == 0 && i != 0 ) {
            out << "  ";
        }
        out << std::hex;
        out << std::setfill('0') << std::setw(2) << static_cast<unsigned>(buffer[i]) << " ";
        out << std::dec;
    }
    return out.str();
}

int main( void )
{
    struct sockaddr_ll saddr = {0};
    socklen_t saddr_size = sizeof(saddr);
    unsigned char packet[1500] = {0};

    int sockFd = socket( AF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
    if( sockFd < 0 ) {
        std::cerr << "Error creating socket!\n";
        return 1;
    }

    int data_size = recvfrom( sockFd, packet, sizeof( packet ), 0, (struct sockaddr*)&saddr, &saddr_size );
    if( data_size == -1 ) {
        std::cerr << "Error in recvfrom()\n";
        return 2;
    }

    std::cout << std::hex;
    std::cout << std::setw( 8 ) << ntohs( 0xADDE ) << "\n";
    std::cout << std::dec;
    std::cout << BufferInHex( packet, data_size ) << "\n";
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
std::string BufferInHex(无符号字符*缓冲区,整数长度)
{
std::ostringstream out;
for(int i=0;iout与问题无关:在第一个for循环中,您需要一个;而不是一个。另外,std::hex和std::dec在BufferInHex中不会流式输出。除此之外,它对我来说运行良好。我注意到saddr_大小设置为零,这并不重要,因为您无论如何都不使用saddr。但这有点奇怪。要进行调试,了解以下错误会有所帮助recvfrom正在提供。您可以使用strerror(errno)@sj0h打印它:
saddr\u大小
确实很重要。它告诉
recvfrom()有多大
saddr`,然后
recvfrom()
才能填充它。这是一个输入/输出参数,您必须用
saddr
的实际大小初始化
saddr\code>,然后
recvfrom()
将更新
saddr\u size
以指定保存在
saddr
中的地址的实际大小。由于代码直接使用
sockaddr
(应使用
sockaddr\u ll
sockaddr\u pkt
),因此
recvfrom()
如果接收到的数据包的地址太大,以至于
saddr
无法访问,它将失败。
sockaddr
不够大,无法容纳IPv6地址。我认为它只是在字段太小时截断了addr,所以这是需要记住的。不过,它似乎没有解释为什么流操作会uld会影响行为。我会更改sockaddr以使用正确的结构,然后看看会发生什么。我也用gdb完成了它,没有人对我大喊大叫。我在虚拟机上,所以可能是环境问题,但我以前从未遇到过这个问题。如果奇怪的地方没有出现,请尝试添加“死亡”再输出几次消息,看看这是否会导致一些奇怪的行为,在我的大型程序中,每隔一段时间它就会开始工作,但如果我添加另一个输出语句,它就会再次失败。谢谢您的帮助。