博客首页
  • 用户名
  • 密码
  • 验证码
  • 网校首页
  • 博客首页
  • 论坛首页
逍遥游!!
乘天地之正,而御六气之辩!
个人资料
_lzt_ 性别:男    所在地:北京市
2010年02月26日 12:04

#include “stdio.h”
#include “stdlib.h”
#include “string.h”
#include “libmemcached/memcached.h”

//gcc -o cc cc.c  -L /usr/local/lib -lmemcached
int main(int argc, char *argv[])
{
    memcached_st *memc;
    memcached_return rc;
    memca

日志分类:c  阅读(3825) | 评论(6) | 打印

2010年02月20日 10:26

名称:
  sscanf() - 从一个字符串中读进与指定格式相符的数据.
  函数原型:
  Int sscanf( string str, string fmt, mixed var1, mixed var2 … );
  int scanf( const char *format [,argument]… );
  说明:
  sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
  其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type

日志分类:c  阅读(537) | 评论(0) | 打印

2010年02月04日 14:41

http://www.kuqin.com/language/20090322/41866.html
typedef 声明,简称 typedef,为现有类型创建一个新的名字。比如人们常常使用 typedef 来编写更美观和可读的代码。所谓美观,意指 typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。

第一、四个用途
用途一:
定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:
char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,
// 和一个字符变量;

日志分类:c  阅读(288) | 评论(2) | 打印

2010年02月01日 10:48

 结构体实例(包括共用体)和类实例的初始化方法完全相同,二者都可以应用于继承层次中。不同点是结构体(包括共用体)默认成员为public,而类默认成员是private型的。
struct T
  {
      int a;
      double b;
     }test = {123};

此时a为123
一、若类和结构体所有数据成员均为public型,可采取如下带花括号形式进行初始化。
 &

日志分类:c  阅读(1641) | 评论(0) | 打印

2010年01月11日 14:20

c++中的explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有”显式”那么必然就有”隐式”,那么什么是显示而什么又是隐式的呢?

如果c++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象,如下面所示:

 
class MyClass
{
public:
MyClass( int num );
}
….
MyClass obj = 10; //ok,convert int to MyClass

在上面的代码中编译器自动将整型转换为MyClass类对象,实际上等同于下面

日志分类:c  阅读(430) | 评论(2) | 打印

2010年01月04日 14:17

http://www.maycode.com/index.php/linux/54-linuxdevelop/1223-pcre.html

日志分类:c  阅读(328) | 评论(1) | 打印

2009年10月22日 12:14

Linux下的地址解析函数应用实例
 

 

 

Linux下的地址解析函数应用实例

作者: 默难 ( monnand@gmail.com )

0    引言
域名系统(DNS)是一种用于TCP/IP应用程序的分布式数据库, 它提供主机名字和IP地址之间的转换及有关电子邮件的选路信息.[1] 目前, 它已经在全球范围内被广泛应用. 从应用的角度上看, 对DNS的访问是通过一个地址解析器(resolver)来完成的. 本文通过讲解一些常用的地址解析函数, 并利用精简后的部分qmail代码, 让不熟悉DNS相关函数的程序员了解并掌握常用的地址解析函数.

1    概述
DNS 查询中, 最常用的两类分别是A类查询(A query)和指针查询(PTR query). 前者是已知主机名, 询问IP; 后者是已知IP, 询问主机名. 对于这些查询, 在Unix主机中可以直接调用基本DNS函数: gethostbyname(3)和gethostbyaddr(3)来实现. 但是对于其他类型的查询(例如MX查询), 则没有专门的函数来负责处理. 此时, 程序员不得不依赖地址解析函数来亲自处理这些问题. 这需要对DNS报文格式有基本的了解, 这些将在下面几节进行说明. 关于gethostbyname(3)和gethostbyaddr(3)两个函数, 读者可以查阅自己系统上的man手册.

2    DNS报文格式
在对地址解析函数讲解之前, 有必要先了解一下DNS报文格式. 之后的几节会频繁地涉及到本节所讲的内容. 如果想对DNS相关协议有更深的了解, 可以阅读参考文献[1] [2] [3].

DNS定义了一个用于查询和响应的报文格式, 图1 显示了这个报文的总体格式.

[图1]

每个DNS查询(或响应)报文都包含有一个12字节长的首部和四个变长的字段组成.

对于本文来说, 首部中主要关心的是问题数和资源记录数两个字段. 这两个字段分别用于说明各自对应的变长字段中的条目数. 问题数说明查询问题字段中的条目数; 资源记录数则说明回答字段中的条目数. 对于一个DNS查询报文, 问题数通常是1. 对于应答报文, 回答数至少是1.

首部以下是四个变长字段, 本文所关心的是查询问题字段和回答字段.

查询问题字段可以包含多个查询问题, 每个问题的格式如图2 所示.

[图2]

其中, 查询名一项存储着要查找的名字. 它长度可变并以一种特殊的格式存储. 程序可以通过其中存储的内容确定其长度. 具体获得其中存储内容的方法, 将在下一节中进行详细讲解. 每一个问题有一个查询类型, 每个响应(下文中将会提到)也同样有一个类型. 常用的类型有: A类型—表示期望获得查询名的IP地址; PTR查询—表示期望获得一个IP地址对应的域名; MX查询—邮件交换查询(关于MX查询的具体内容, 下文会提到). 查询类指定了所使用的协议簇, 通常是1, 表示Internet地址.

回答字段可以包含多个条目. 每个回答字段是以一种叫做资源记录(Resource Record, RR)的格式存储的. ( 授权字段和额外信息字段也同样以资源记录的格式存储信息). 资源记录的格式如图3 所示.

[图3]

域名是记录中资源数据对应的名字. 它的格式和前面介绍的查询名字段格式相同. 类型和类字段和前面介绍的查询类型, 查询类字段的功能一样. 类字段的取值通常是1, 表示Internet地址. 生存时间字段是客户程序保留该资源记录的秒数. 资源数据长度说明资源数据包含的字节数. 资源数据则根据类型字段的值有不同的格式. 对于A类型, 资源数据是IP地址. 对于MX查询, 资源数据是优先值和域名, 域名的格式与查询名字段格式相同(MX记录的具体内容下文会有介绍).

至此, DNS中用到的报文格式已经基本介绍完. 下一节中将会介绍一些常用的地址解析函数. 阅读下文时, 最好随时翻阅本节所讲的内容以便于理解.

3    地址解析函数

除了经常用到的gethostbyname(3)和gethostbyaddr(3)函数以外, Linux(以及其它UNIX/UNIX-like系统)还提供了一套用于在底层处理DNS相关问题的函数(这里所说的底层仅是相对 gethostbyname和gethostbyaddr两个函数而言). 这套函数被称为地址解析函数(resolver functions). 用户可以通过键入man resolver来了解其中的具体信息. 这里将对其中常用到的函数做一个解释. 常用的地址解析函数原型如下:
       #include
       #include
       #include
       extern struct state _res;

       int res_init(void);

       int res_query(const char *dname, int class, int type,
              unsigned char *answer, int anslen);

       int res_search(const char *dname, int class, int type,
              unsigned char *answer, int anslen);

       int dn_expand(unsigned char *msg, unsigned char *eomorig,
              unsigned char *comp_dn, unsigned char *exp_dn,
              int length);

_res: 这个结构体用于保存相关的状态信息. 它的定义在中.

res_init: 读取配置文件并修改环境变量:LOCALDOMAIN. 在调用其他地址解析函数前通常要先调用res_init. 如果执行成功, 函数返回0; 否则返回-1.

res_query:  用来发出一个指定类(由参数class指定)和类型(由参数type指定)的DNS询问. dname是要查询的主机名. 返回信息被存储在answser指向的内存区域中. 信息的长度不能大于anslen个字节. 这个函数会创建一个DNS查询报文并把它发送到指定的DNS服务器.

res_search: 和res_query的行为类似, 与res_query不同的是, 当域名中不包含点时, 会在域名后面加上默认域名; 同时, 支持递归查询(即当一个服务器没有存储询问的信息时, 会继续向其他服务器询问). 一般情况下尽量使用res_search. 因为它的成功几率会比较大.

res_query和res_search函数返回值是响应报文的长度; 如果发生错误则返回-1.

dn_expand: 上一节中已经说到, DNS报文中主机名是以一种特殊格式存储的. dn_expand函数则是将这种特殊格式存储的字符串还原成一般格式. msg参数值是整个DNS报文的首地址; eomorig参数指向DNS报文的最后一个字节后的一字节, 用于指定报文的结束位置; comp_dn参数指向报文中需要被还原的主机名的首地址; 还原后的主机名被存储在exp_dn指向的内存区域中, 长度不大于length个字节. 函数返回主机名在DNS报文中的长度(即被还原前的长度); 如果发生错误则返回-1.

需要注意的是, 如果程序中用到了这些地址解析函数, 那么在编译的时候需要加上-lresolv选项才能正常编译.

利用这些地址解析函数, 不仅可以完成A类查询或PTR查询, 还可以进行其他类型的询问. 下一节将给出利用地址解析函数进行MX查询的实例.

4    地址解析函数应用实例—MX查询
在发送电子邮件时, 需要用到MX(Mail eXchange)记录. 一个电子邮箱的地址是 "用户名@域名" 的格式. 当要给某个用户发送电子邮件时, 首先需要从这个用户的电子邮箱地址中得到域名; 然后向DNS服务器发出一个MX查询, 询问该域名由哪些服务器负责处理.DNS服务器会返回处理该域名的服务器的主机名. 每个主机名对应一个16bit的整数值, 该值称为优先值(preference value), 如果一个域存在多条MX记录, 则首先使用优先值较小的主机名. 之后, 就是利用SMTP协议与相应的主机进行连接并发送邮件.

如果要发出一个MX查询, 可以利用host命令:

    [monnand@monnand-host ~]$ host -t mx gmail.com
    gmail.com mail is handled by 50 gsmtp183.google.com.
    gmail.com mail is handled by 5 gmail-smtp-in.l.google.com.
    gmail.com mail is handled by 10 alt1.gmail-smtp-in.l.google.com.
    gmail.com mail is handled by 10 alt2.gmail-smtp-in.l.google.com.
    gmail.com mail is handled by 50 gsmtp163.google.com.

-t 选项用于指明查询类型, -t mx表示发起一个MX查询. 后面的参数是要查询的域名(这里以gmail.com为例).
显示出的是关于查询域名的MX记录. 这里关于gmail.com的MX记录共5条, 每条记录都有相应的优先值(显示在主机名前面), 例如第一条记录的优先值是50.

下面, 我们就利用前面讲到的地址解析函数来实现一个类似功能的程序. 即指定查询域名, 打印出关于这个域名的MX记录. 该程序的代码是从qmail的代码中精简出来的, 其中去掉了一些错误检测, 并修改了与qmail其他部分相关联的代码, 使整个程序能够独立出来(当然, 因为去掉了很多错误检测, 程序也失去了原有的健壮性和安全性). 但是整体的思路基本没有大的改动. 有兴趣的读者可以自己阅读qmail的源代码. 相信会有更多的收获.

整个程序被写到了两个文件中, 分别名为dns.h和dns.c.

以下是dns.h中的内容:

1    #ifndef DNS_H
2    #define    DNS_H
3     
4    #define    DNS_MSG_END    -2
5     
6    #define    dns_mx_query(str)    dns_resolve((str),T_MX)
7    #define    dns_mx_expand()        dns_findmx(T_MX)
8     
9    #define    foreach_mxrr(p,dn)    while(dns_mx_expand()!=DNS_MSG_END   
10                        &&(!dns_get_mxrr(&p,dn,MAXDNAME)))
11     
12    void dns_init(void);
13    int dns_get_mxrr(unsigned short *,unsigned char *,unsigned int);
14    int dns_resolve(char *,int);
15    int dns_findmx(int);
16     
17    #endif /* #ifndef MONNAND_DNS_H */

该文件中声明了4个函数. 为了便于操作, 定义了三个宏. 关于其中具体的用法, 之后会有介绍. 下面给出dns.c中的源代码:

1    #include
2    #include
3    #include
4    #include
5    #include
6    #include
7    #include
8    #include
9    #include
10     
11    #include "dns.h"
12     
13    extern int res_query();
14    extern int res_search();
15    extern int errno;
16    extern int h_errno;
17     
18    static unsigned short getshort(unsigned char *c) { unsigned short u; u = c[0]; return (u 0)
44        {
45            i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
46            responsepos += i;
47            i = responseend - responsepos;
48            if(i < QFIXEDSZ) return -1;
49            responsepos += QFIXEDSZ;
50        }
51        numanswers = ntohs(response.hdr.ancount);
52        return numanswers;
53    }
54     
55    int dns_findmx(int wanttype)
56    {
57        unsigned short rrtype;
58        unsigned short rrdlen;
59        int i;
60     
61        if(numanswers

日志分类:c  阅读(761) | 评论(3) | 打印



array(2) { ["submit"]=> string(0) "" ["s"]=> string(0) "" } here