基于libpcap的开发实例

libpcap是Unix/Linux平台中用于网络数据包捕获的函数库(Windows版本为winpcap)。本文通过实例来说明其使用方法。

1 安装libpcap库

TCPDUMP官网下载最新的libpcap源代码,解压到本地后,编译并安装即可,注意安装时需要使用root权限。

./configure
make
make install

2 实例代码

代码完成的功能是抓取指定网卡的数据包,并将数据交给回调函数处理(这里回调函数只是打了个桩,没有做实质性的处理)。

首先定义一个基本类型的头文件(basetype.h),将数据类型封装一下:

#ifndef _BASETYPE_H_
#define _BASETYPE_H_

#define OK (0)
#define ERROR (1)

#define YES (1)
#define NO (0)

typedef void VOID;

typedef char CHAR;
typedef char …

类型转换导致字符串大小计算错误的问题

今天在定位问题时,发现有一个字符串关键字在搜索时死活不命中,但实际那个关键字在数据中是存在的,跟踪发现是一个不起眼的细节导致的。

用一段简短的代码来说明一下问题出在哪里:

#include <stdio.h>

#define M_STRING_1 "test"
#define M_STRING_2 (char *)"test"

int main(int argc, char *argv[])
{
    char *pcStr = M_STRING_1;

    printf("Size of string macro 1      : %u bytes \r\n", sizeof(M_STRING_1));
    printf("Size of string pointer 1    : %u bytes \r\n", sizeof(pcStr));
    printf("Size …

Linux信号处理机制

在Linux中,信号是进程间通讯的一种方式,它采用的是异步机制。当信号发送到某个进程中时,操作系统会中断该进程的正常流程,并进入相应的信号处理函数执行操作,完成后再回到中断的地方继续执行。

需要说明的是,信号只是用于通知进程发生了某个事件,除了信号本身的信息之外,并不具备传递用户数据的功能。

1 信号的响应动作

每个信号都有自己的响应动作,当接收到信号时,进程会根据信号的响应动作执行相应的操作,信号的响应动作有以下几种:

  • 中止进程(Term)
  • 忽略信号(Ign)
  • 中止进程并保存内存信息(Core)
  • 停止进程(Stop)
  • 继续运行进程(Cont)

用户可以通过signalsigaction函数修改信号的响应动作(也就是常说的“注册信号”,在文章的后面会举例说明)。另外,在多线程中,各线程的信号响应动作都是相同的,不能对某个线程设置独立的响应动作。

2 信号类型

Linux支持的信号类型可以参考下面给出的列表。

2.1 在POSIX.1-1990标准中的信号列表

信号 动作 说明 …

函数调用栈的获取原理分析

上一篇文章《在Linux程序中输出函数调用栈》,讲述了在Linux中如何利用backtrace获取调用栈,本篇文章主要介绍一下获取函数调用栈的原理,并给出相应的实现方式。

要了解调用栈,首先需要了解函数的调用过程,下面用一段代码作为例子:

#include <stdio.h>

int add(int a, int b) {
    int result = 0;

    result = a + b;

    return result;
}

int main(int argc, char *argv[]) {
    int result = 0;

    result = add(1, 2);

    printf("result = %d \r\n", result);

    return 0;
}

使用gcc编译,然后gdb反汇编main函数,看看它是如何调用add函数的:

(gdb …

在Linux程序中输出函数调用栈

程序发生异常时,将函数的调用栈打印出来,可以大大提高定位效率。

Linux中提供了三个函数用来获取调用栈:

/* 获取函数调用栈 */
int backtrace(void **buffer, int size);

/* 将调用栈中的函数地址转化为函数名称 并返回一个字符串数组 */
char **backtrace_symbols(void *const *buffer, int size);

/* 将调用栈中的函数地址转化为函数名称 并将其定入到文件中 */
void backtrace_symbols_fd(void *const *buffer, int size, int fd);

示例代码:

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

/* 打印调用栈的最大深度 */
#define DUMP_STACK_DEPTH_MAX 16

/* 打印调用栈函数 */
void dump_trace() {
    void *stack_trace …

标记ATL控件为安全控件

用ATL开发网页控件时,IE总会出现“该控件不是安全的”之类的提示,去掉这个提示的方法就是使用 IObjectSafety 将其标记为可安全初始化的控件。

实现方法如下:

首先在需要将 IObjectSafetyImpl 添加到该控件的派生类中,然后在映射列表中添加 IObjectSafety,具体添加的代码如下:

class CHutaow : 
    // 添加到控件的派生类列表中
    public IObjectSafetyImpl<CHutaow, INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA>
    ...
    {
        public:

        BEGIN_COM_MAP(CHutaow)

        COM_INTERFACE_ENTRY(IObjectSafety) //创建IObjectSafety的映射

        ...

        END_COM_MAP()
        ...
    }

PS: 如果出现"'IObjectSafetyImpl' : base class undefined"的错误,则需要添加"atlctl.h"头文件。