一台设备上同时有两个pcap_compile()?

时间:2014-12-02 09:18:33

标签: c++ winpcap

我有两个线程,每个线程同时从同一个deviсe捕获数据包,但是当第二个线程到达pcap_compile()函数时程序崩溃。此外,每个线程都有自己的变量,不使用全局变量。看起来他们获得了相同的设备句柄,因此程序崩溃了。为什么我需要两个线程?因为我想在已发送的和由指定的pcap过滤器接收的数据包上分离数据包。那么我该如何解决这个问题呢?或者,使用一个线程并使用tcp标题中的地址手动对发送和接收的数据包进行排序更好?

2 个答案:

答案 0 :(得分:2)

pcap_compile 线程安全。您必须包含对具有临界区/互斥锁的单独线程可能遇到的所有调用,以防止错误,因为解析器中编译表达式的非线程安全状态(对于血淋淋的细节,它使用YACC创建代码解析表达式并为其生成的代码显然不是线程安全的。)

您需要为每次计划用于捕获的线程明确地打开设备一次,如果您在多个线程中重复使用相同的设备句柄,那么它将无法满足您的要求。您应该在您计划使用它的线程中打开pcap句柄,因此计划捕获的每个线程都应该自己执行pcap_open

使用Critical Section来保护对pcap_compile的调用,你可以创建一个简单的包装器(Windows关键部分的C ++包装器):

class lock_interface {
public:
    virtual void lock() = 0;
    virtual void unlock() = 0;
};

class cs : public lock_interface {
    CRITICAL_SECTION crit;
public:
    cs() { InitializeCriticalSection(&crit); }
    ~cs() { DeleteCriticalSection(&crit); }
    virtual void lock() {
        EnterCriticalSection(&crit);
    }
    virtual void unlock() {
        LeaveCriticalSection(&crit);
    }
private:
    cs(const locker &);
    cs &operator=(const cs &);
};

class locker {
    lock_interface &m_ref;
public:
    locker(lock_interface &ref) : m_ref(ref) { m_ref.lock(); }
    ~locker() { m_ref.unlock(); }
private:
    locker(const locker &);
    locker &operator=(const locker &);
};

static cs section;

int
wrapped_pcap_compile(pcap_t *p, struct bpf_program *fp, const char *str, int optimize, bpf_u_int32 netmask)
{
    locker locked(section);
    pcap_compile(p, fp, str, optimize, netmask);
}

答案 1 :(得分:1)

如果您使用的是C ++ 11,则可能会有类似的内容:

int thread_safe_pcap_compile_nopcap(int snap_len, int link_type,
                                    struct bpf_program *fp, char const *str,
                                    int optimize, bpf_u_int32 netmask) {
    static std::mutex mtx;
    std::lock_guard<std::mutex> lock(mtx);
    return pcap_compile_nopcap(snap_len, link_type, fp, str, optimize, netmask);
}

pcap_compile函数相似。