﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-一江春水向东流-文章分类-TCP/IP 开发</title><link>http://www.blogjava.net/huyi2006/category/21638.html</link><description>                            做一个有思想的人</description><language>zh-cn</language><lastBuildDate>Thu, 10 Apr 2008 23:46:47 GMT</lastBuildDate><pubDate>Thu, 10 Apr 2008 23:46:47 GMT</pubDate><ttl>60</ttl><item><title>关于TCP重组[转]</title><link>http://www.blogjava.net/huyi2006/articles/192016.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Thu, 10 Apr 2008 15:01:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/192016.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/192016.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/192016.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/192016.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/192016.html</trackback:ping><description><![CDATA[
		<p> 重装TCP数据段，我看了《TCP/IP详解卷二：实现》觉得它里面的实现考虑的很全面，当然也就很复杂。而我组装只是为了监视,所以不必那么复杂，于是自己想了一个方法。现在我已经根据这个方法成功组装TCP分段，所以这个方法是可行的。另外，我的IP分片的组装用的方法跟这个方法也差不多。</p>
		<p>    首先说下存储tcp分段的数据结构：一个二维链表，我把它叫作重装表。具有相同socket对（源ip地址、目的ip地址、源端口号、目的端口号）的tcp数据包放在一个横向的链表里，该链表的头节点只保存了源ip地址、目的ip地址、源端口号、目的端口号这些信息。如下图所示： </p>
		<p> </p>
		<p>    然后介绍重装TCP数据段的方法：</p>
		<p>1.每到来一个tcp数据包(pkt)，我先将该数据包的源ip地址、目的ip地址、源端口号、目的端口号取出来在重装表（tpq_tbl）中纵向的链表中查找有没有与它相匹配的链表(fp)存在，如果有，就把pkt数据包放入与它有相同socket对的fp链中，放入链表的时，我先查找pkt的顺序号在链表中的适当位置，然后才放入；如果没有，则在tpq_tbl中新创建一个该类型的链表头节点，然后再将其放入新创建的链表中。</p>
		<p>2.每当在fp中放入一个tcp数据段后，我就检查fp链表中的数据段是否已经到齐了（判断方法下面介绍），若到齐，就将个链表中所有数据段的数据部分拼接到一起，得到应用层报文，然后释放该链表，然后重复1－2步骤；若没到齐，直接重复1－2步骤。</p>
		<p> 关于判断一个链表中tcp数据段是否到齐的方法：<br />    使用的变量说明：<br />    count计数器，表示当前链表中的所有tcp数据段数据部分的长度之和。每当在该链表中加入一个新tcp数据段时，我都会将count累加上该tcp数据段的数据部分的长度。<br />    syn_seq，表示本次tcp连接的第一个数据包的顺序号，也就是建立tcp连接时的第一次握手的SYN包的顺序号。<br />    fin_seq，表示本次tcp连接的最后一个数据包的顺序号，也就是关闭tcp连接时的第二个FIN包的顺序号。</p>
		<p>    判断：当(fin_seq - syn_seq)与count相等时，就说明tcp数据段已经到齐，否则就是没有到齐。<br /></p>
<img src ="http://www.blogjava.net/huyi2006/aggbug/192016.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2008-04-10 23:01 <a href="http://www.blogjava.net/huyi2006/articles/192016.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux网络编程-- 服务器模型</title><link>http://www.blogjava.net/huyi2006/articles/189520.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Sat, 29 Mar 2008 12:14:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/189520.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/189520.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/189520.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/189520.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/189520.html</trackback:ping><description><![CDATA[ 在网络程序里面,一般的来说都是许多客户机对应一个服务器.为了处理客户机的请求, 对服务端的程序就提出了特殊的要求.我们学习一下目前最常用的服务器模型.<br /><br />循环服务器:循环服务器在同一个时刻只可以响应一个客户端的请求<br /><br />并发服务器:并发服务器在同一个时刻可以响应多个客户端的请求<br /><br /><br />9.1 循环服务器:<br /><br />UDP服务器<br />UDP循环服务器的实现非常简单:<br />UDP服务器每次从套接字上读取一个客户端的请求,处理, 然后将结果返回给客户机.<br /><br />可以用下面的算法来实现.<br /><br />    socket(...);<br />    bind(...);<br />    while(1)<br />    {<br />        recvfrom(...);<br />        process(...);<br />        sendto(...);<br />    }<br /><br />因为UDP是非面向连接的,没有一个客户端可以老是占住服务端. 只要处理过程不是死循环, 服务器对于每一个客户机的请求总是能够满足.<br /><br />9.2 循环服务器:<br /><br />TCP服务器<br />TCP循环服务器的实现也不难:TCP服务器接受一个客户端的连接,然后处理,完成了这个客户的所有请求后,断开连接.<br /><br />算法如下:<br /><br />socket(...);<br />bind(...);<br />listen(...);<br /><br />while(1)<br />{<br />    accept(...);<br />    while(1)<br />    {<br />        read(...);<br />        process(...);<br />        write(...);<br />    }<br />    close(...);<br />}<br /><br />TCP循环服务器一次只能处理一个客户端的请求.只有在这个客户的所有请求都满足后, 服务器才可以继续后面的请求.这样如果有一个客户端占住服务器不放时,其它的客户机都不能工作了.因此,TCP服务器一般很少用循环服务器模型的.<br /><br />9.3 并发服务器:     TCP服务器<br />为了弥补循环TCP服务器的缺陷,人们又想出了并发服务器的模型. 并发服务器的思想是每一个客户机的请求并不由服务器直接处理,而是服务器创建一个 子进程来处理.<br /><br />算法如下:<br /><br />    socket(...);<br />    bind(...);<br />    listen(...);<br />    while(1)<br />    {<br />        accept(...);<br />        if(fork(..)==0)<br />        {<br />                while(1)<br />                {<br />                    read(...);<br />                    process(...);<br />                    write(...);<br />                }<br />                close(...);<br />                exit(...);<br />        }<br />    close(...);<br />    }<br /><br />TCP并发服务器可以解决TCP循环服务器客户机独占服务器的情况. 不过也同时带来了一个不小的问题.<br />为了响应客户机的请求,服务器要创建子进程来处理. 而创建子进程是一种非常消耗资源的操作.<br /><br />9.4 并发服务器:<br /><br />多路复用I/O<br />为了解决创建子进程带来的系统资源消耗,人们又想出了多路复用I/O模型.<br /><br />首先介绍一个函数select<br /><br />int select(int nfds,<br />        fd_set *readfds,fd_set *writefds,<br />      fd_set *except fds,<br />      struct timeval *timeout<br />      )<br /><br />void FD_SET(int fd,fd_set *fdset)<br /><br />void FD_CLR(int fd,fd_set *fdset)<br /><br />void FD_ZERO(fd_set *fdset)<br /><br />int FD_ISSET(int fd,fd_set *fdset)<br /><br />一般的来说当我们在向文件读写时,进程有可能在读写出阻塞,直到一定的条件满足.<br /><br /> 比如我们从一个套接字读数据时,可能缓冲区里面没有数据可读(通信的对方还没有发送数据过来),<br /> 这个时候我们的读调用就会等待(阻塞)直到有数据可读.如果我们不 希望阻塞,<br /> 我们的一个选择是用select系统调用. <br /> <br /> 只要我们设置好select的各个参数,那么当文件可以读写的时候select回"通知"我们 说可以读写了. <br /> readfds所有要读的文件  文件描述符的集合<br />writefds所有要写的文件   文件描述符的集合<br /><br />exceptfds其他的服要向我们通知的文件描述符<br /><br />timeout超时设置.<br /><br />nfds所有我们监控的文件描述符中最大的那一个加1<br /><br />在我们调用select时进程会一直阻塞直到以下的一种情况发生. <br />1)有文件可以读.<br />2)有文件可以写.<br />3)超时所设置的时间到.<br /><br />为了设置文件描述符我们要使用几个宏. FD_SET将fd加入到fdset<br /><br />FD_CLR将fd从fdset里面清除<br /><br />FD_ZERO从fdset中清除所有的文件描述符<br /><br />FD_ISSET判断fd是否在fdset集合中<br /><br />使用select的一个例子<br /><br />int use_select(int *readfd,int n)<br />{<br />        fd_set my_readfd;<br />        int maxfd;<br />        int i;<br />        <br />        maxfd=readfd[0];<br />        <br />        for(i=1;i&lt;n;i++)<br />        {<br />            if(readfd[i]&gt;maxfd) maxfd=readfd[i];<br />        }<br />        <br />        <br />        <br />        while(1)<br />        {<br />            /* 将所有的文件描述符加入 */<br />            FD_ZERO(&amp;my_readfd);<br />            <br />            for(i=0;i&lt;n;i++)<br />            FD_SET(readfd[i],*my_readfd);<br />            <br />            /* 进程阻塞 */<br />            select(maxfd+1,&amp; my_readfd,NULL,NULL,NULL);<br />            <br />            /* 有东西可以读了 */<br />            for(i=0;i&lt;n;i++)<br />            {<br />                if(FD_ISSET(readfd[i],&amp;my_readfd))<br />                {<br />                        /* 原来是我可以读了 */<br />                        we_read(readfd[i]);<br />                }<br />            }<br />        }<br />}<br /><br />使用select后我们的服务器程序就变成了.<br /><br /><br />初始话(socket,bind,listen);<br /><br />while(1)<br />{<br />        设置监听读写文件描述符(FD_*);<br />        <br />        调用select;<br />        <br />        如果是倾听套接字就绪,说明一个新的连接请求建立<br />        {<br />            建立连接(accept);<br />            加入到监听文件描述符中去;<br />        }<br />        否则说明是一个已经连接过的描述符<br />        {<br />            进行操作(read或者write);<br />        }<br /><br />}<br /><br />多路复用I/O可以解决资源限制的问题.着模型实际上是将UDP循环模型用在了TCP上面. 这也就带来了一些问题.如由于服务器依次处理客户的请求,所以可能会导致有的客户 会等待很久.<br /><br /> 并发服务器:        UDP服务器<br />人们把并发的概念用于UDP就得到了并发UDP服务器模型. <br /> 并发UDP服务器模型其实是简单的.和并发的TCP服务器模型一样是<br /> 创建一个子进程来处理的 算法和并发的TCP模型一样.<br /><br />除非服务器在处理客户端的请求所用的时间比较长以外,人们实际上很少用这种模型. <br /><img src ="http://www.blogjava.net/huyi2006/aggbug/189520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2008-03-29 20:14 <a href="http://www.blogjava.net/huyi2006/articles/189520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(C)libpcap函数库说明</title><link>http://www.blogjava.net/huyi2006/articles/139179.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Fri, 24 Aug 2007 13:07:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/139179.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/139179.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/139179.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/139179.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/139179.html</trackback:ping><description><![CDATA[
		<p>(C)libpcap函数库说明</p>
		<p>libpcap获取数据包函数库说明</p>
		<p>libpcap的英文意思是 Packet Capture library，即数据包捕获函数库。该库提供的C函数接口可用于</p>
		<p>需要捕获经过网络接口（只要经过该接口，目标地址不一定为本机）数据包的系统开发上。由 </p>
		<p>Berkeley大学Lawrence Berkeley National  Laboratory研究院的Van Jacobson、Craig Leres和</p>
		<p>Steven McCanne编写，目前的最新版本为0.4。该函数库支持Linux、Solaris和*BSD系统平台。 </p>
		<p>主要接口函数说明如下：<br /> <br />pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) <br />获得用于捕获网络数据包的数据包捕获描述字。device参数为指定打开的网络设备名。snaplen参数定</p>
		<p>义捕获数据的最大字节数。promisc指定是否将网络接口置于混杂模式。to_ms参数指定超时时间（毫</p>
		<p>秒）。ebuf参数则仅在pcap_open_live()函数出错返回NULL时用于传递错误消息。 </p>
		<p>pcap_t *pcap_open_offline(char *fname, char *ebuf) <br />打开以前保存捕获数据包的文件，用于读取。fname参数指定打开的文件名。该文件中的数据格式与</p>
		<p>tcpdump和tcpslice兼容。"-"为标准输入。ebuf参数则仅在pcap_open_offline()函数出错返回NULL时</p>
		<p>用于传递错误消息。 </p>
		<p>pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname)<br />打开用于保存捕获数据包的文件，用于写入。fname参数为"-"时表示标准输出。出错时返回NULL。p参</p>
		<p>数为调用pcap_open_offline()或pcap_open_live()函数后返回的pcap结构指针。fname参数指定打开</p>
		<p>的文件名。如果返回NULL，则可调用pcap_geterr()函数获取错误消息。 </p>
		<p>char *pcap_lookupdev(char *errbuf) <br />用于返回可被pcap_open_live()或pcap_lookupnet()函数调用的网络设备名指针。如果函数出错，则</p>
		<p>返回NULL，同时errbuf中存放相关的错误消息。 </p>
		<p>int pcap_lookupnet(char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf) <br />获得指定网络设备的网络号和掩码。netp参数和maskp参数都是bpf_u_int32指针。如果函数出错，则</p>
		<p>返回-1，同时errbuf中存放相关的错误消息。 </p>
		<p>int pcap_dispatch(pcap_t *p, int cnt,pcap_handler callback, u_char *user) <br /> 捕获并处理数据包。cnt参数指定函数返回前所处理数据包的最大值。cnt=-1表示在一个缓冲区中处</p>
		<p>理所有的数据包。cnt=0表示处理所有数据包，直到产生以下错误之一：读取到EOF；超时读取。</p>
		<p>callback 参数指定一个带有三个参数的回调函数，这三个参数为：一个从pcap_dispatch()函数传递</p>
		<p>过来的u_char指针，一个pcap_pkthdr结构libpcap函数库说明。bsp;  的指针，和一个数据包大小的</p>
		<p>u_char指针。如果成功则返回读取到的字节数。读取到EOF时则返回零值。出错时则返回-1，此时可调</p>
		<p>用pcap_perror()或pcap_geterr()函数获取错误消息。 </p>
		<p>int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) <br />功能基本与pcap_dispatch()函数相同，只不过此函数在cnt个数据包被处理或出现错误时才返回，但</p>
		<p>读取超时不会返回。而如果为pcap_open_live()函数指定了一个非零值的超时设置，然后调用</p>
		<p>pcap_dispatch()函数，则当超时发生时pcap_dispatch()函数会返回。cnt参数为负值时pcap_loop()</p>
		<p>函数将始终循环运行，除非出现错误。 </p>
		<p>void pcap_dump(u_char *user, struct pcap_pkthdr *h, u_char *sp) <br />向调用pcap_dump_open()函数打开的文件输出一个数据包。该函数可作为pcap_dispatch()函数的回调</p>
		<p>函数。 </p>
		<p>int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 </p>
		<p>netmask) <br />将str参数指定的字符串编译到过滤程序中。fp是一个bpf_program结构的指针，在pcap_compile()函</p>
		<p>数中被赋值。optimize参数控制结果代码的优化。netmask参数指定本地网络的网络掩码。 <br />         <br />int pcap_setfilter(pcap_t *p, struct bpf_program *fp) <br />指定一个过滤程序。fp参数是bpf_program结构指针，通常取自pcap_compile()函数调用。出错时返回</p>
		<p>-1；成功时返回0。 </p>
		<p>u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h) <br />返回指向下一个数据包的u_char指针。 </p>
		<p>int pcap_datalink(pcap_t *p) <br />返回数据链路层类型，例如DLT_EN10MB。 </p>
		<p>int pcap_snapshot(pcap_t *p) <br />返回pcap_open_live被调用后的snapshot参数值。 </p>
		<p>int pcap_is_swapped(pcap_t *p) <br />返回当前系统主机字节与被打开文件的字节顺序是否不同。 </p>
		<p>int pcap_major_version(pcap_t *p) <br />返回写入被打开文件所使用的pcap函数的主版本号。 </p>
		<p>int pcap_minor_version(pcap_t *p) <br />返回写入被打开文件所使用的pcap函数的辅版本号。 </p>
		<p>int pcap_stats(pcap_t *p, struct pcap_stat *ps) <br />向pcap_stat结构赋值。成功时返回0。这些数值包括了从开始捕获数据以来至今共捕获到的数据包统</p>
		<p>计。如果出错或不支持数据包统计，则返回-1，且可调用pcap_perror()或  pcap_geterr()函数来获</p>
		<p>取错误消息。 </p>
		<p>FILE *pcap_file(pcap_t *p) <br />返回被打开文件的文件名。 </p>
		<p>int pcap_fileno(pcap_t *p) <br />返回被打开文件的文件描述字号码。 </p>
		<p>void pcap_perror(pcap_t *p, char *prefix) <br />在标准输出设备上显示最后一个pcap库错误消息。以prefix参数指定的字符串为消息头。 </p>
		<p>char *pcap_geterr(pcap_t *p) <br />返回最后一个pcap库错误消息。 </p>
		<p>char *pcap_strerror(int error) <br />如果strerror()函数不可用，则可调用pcap_strerror函数替代。 </p>
		<p>void pcap_close(pcap_t *p) <br />关闭p参数相应的文件，并释放资源。 </p>
		<p>void pcap_dump_close(pcap_dumper_t *p) </p>
		<p>5、Libpcap的主要数据结构：<br /> <br />Libpcap库函数所必须的数据结构定义主要包含在pcap.h和pcap-int.h两个头文件中。其主要数据结构</p>
		<p>如下：<br /> <br />(1)pcap结构<br /> <br />pcap结构在pcap-int.h头文件中被定义：<br /> <br />struct pcap<br />{<br />    int                fd;<br />    int                snapshot;<br />    int                linktype;<br />    int                tzoff;    /* timezone offset                                   */<br />    int                offset;   /* offset for proper alignment                       */<br />    struct pcap_sf     sf;<br />    struct pcap_md     md;<br />    int                bufsize;  /* Read buffer                                       */<br />    u_char *           buffer;<br />    u_char *           bp;<br />    int                cc;<br />    u_char *           pkt;      /* Place holder for pcap_next()                      */<br />    struct bpf_program fcode;    /* Placeholder for filter code if bpf not in kernel. */<br />    char               errbuf[PCAP_ERRBUF_SIZE];<br />};<br /> <br />(2)bpf_program结构<br /> <br />该结构在pcap_compile()函数中被使用，在bpf.h头文件中定义。<br /> <br />/usr/include/net/bpf.h</p>
		<p>/* Structure for BIOCSETF. */<br />struct bpf_program<br />{<br />    u_int             bf_len;<br />    struct bpf_insn * bf_insns;<br />};</p>
		<p>/*<br />* The instruction data structure.<br />*/<br />struct bpf_insn<br />{<br />    u_short   code;<br />    u_char    jt;<br />    u_char    jf;<br />    bpf_int32 k;<br />};<br /> <br />(3)pcap_pkthdr结构<br /> <br />/usr/include/pcap.h</p>
		<p>/*<br />* Each packet in the dump file is prepended with this generic header.<br />* This gets around the problem of different headers for different<br />* packet interfaces.<br />*/<br />struct pcap_pkthdr<br />{<br />    struct timeval ts;      /* time stamp                    */<br />    bpf_u_int32    caplen;  /* length of portion present     */<br />    bpf_u_int32    len;     /* length this packet (off wire) */<br />};</p>
		<p>/usr/include/net/bpf.h</p>
		<p>/*<br />* Structure prepended to each packet.<br />*/<br />struct bpf_hdr<br />{<br />    struct timeval bh_tstamp;   /* time stamp                 */<br />    bpf_u_int32    bh_caplen;   /* length of captured portion */<br />    bpf_u_int32    bh_datalen;  /* original length of packet  */<br />    u_short        bh_hdrlen;   /* length of bpf header (this struct<br />                                   plus alignment padding)    */<br />};<br /> <br />(4)pcap_stat结构<br /> <br />struct pcap_stat {<br />        u_int ps_recv; /* number of packets received */<br />        u_int ps_drop; /* number of packets dropped */<br />        u_int ps_ifdrop; /* drops by interface XXX not yet supported */<br />};<br /><br />int main()<br />{<br />        bpf_u_int32 localnet,netmask;<br />        struct bpf_program fcode;<br />        pcap_handler printer;</p>
		<p>        pcap_dumper_t*p;<br />        char ebuf[PCAP_ERRBUF_SIZE];<br />        char * device;<br />        u_char * pcap_userdata;<br />        pcap_t * pd;<br />        int dev_flag=1;<br />        int cap_len=CAP_LEN;<br />        int i;</p>
		<p>        device=pcap_lookupdev(ebuf);<br />        if (device == NULL)<br />                exit(printf("%s n", ebuf));<br />        #ifdef _DEBUG_<br />        printf("device is %s \n",device);<br />        #endif<br />        pd=pcap_open_live(device,cap_len,dev_flag,1000,ebuf);<br />        if(pd == NULL)<br />                exit(printf("%s\n",ebuf));</p>
		<p>        i=pcap_snapshot(pd);<br />                if(cap_len &lt; i) {<br />                printf("snaplen raised from %d to %d \n", cap_len, i);<br />                        cap_len=i;<br />                }<br />        if(pcap_lookupnet(device, &amp;localnet, &amp;netmask, ebuf) &lt; 0) {<br />                        localnet=0;</p>
		<p>    netmask=0;<br />                        printf("%s\n", ebuf);<br />        }<br />        if (pcap_compile(pd, &amp;fcode, "", 1, netmask) &lt; 0)<br />                exit(printf("Error %s\n","pcap_compile"));<br />        if (pcap_setfilter(pd,&amp;fcode) &lt; 0)<br />                exit(printf("Error %s\n","pcap_setfilter"));</p>
		<p>        p=pcap_dump_open(pd,FILENAME);<br />                if(p == NULL)<br />                        exit(printf("Error:%s\n","pcap_dump_open"));<br />                printer=pcap_dump;<br />                pcap_userdata=(u_char *)p;</p>
		<p>        if(pcap_loop(pd, -1, printer, pcap_userdata) &lt; 0)<br />                exit(printf("Error, %s\n","pcap_loop"));</p>
		<p>        pcap_close(pd);<br />        exit(0);<br />}</p>
		<p> </p>
<img src ="http://www.blogjava.net/huyi2006/aggbug/139179.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2007-08-24 21:07 <a href="http://www.blogjava.net/huyi2006/articles/139179.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket编程中需要用到的头文件</title><link>http://www.blogjava.net/huyi2006/articles/139176.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Fri, 24 Aug 2007 12:54:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/139176.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/139176.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/139176.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/139176.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/139176.html</trackback:ping><description><![CDATA[
		<font face="宋体"> </font>
		<h2 align="left">
				<font size="6">socket编程中需要用到的头文件</font>
		</h2>
		<font size="+2">
				<p>sys/types.h：数据类型定义</p>
				<p>sys/socket.h：提供socket函数及数据结构</p>
				<p>netinet/in.h：定义数据结构sockaddr_in</p>
				<p>arpa/inet.h：提供IP地址转换函数</p>
				<p>netdb.h：提供设置及获取域名的函数</p>
				<p>sys/ioctl.h：提供对I/O控制的函数</p>
				<p>sys/poll.h：提供socket等待测试机制的函数</p>
				<h2> </h2>
				<h2>
				</h2>
		</font>
		<font size="6">其他在网络程序中常见的头文件</font>
		<font size="+2">
				<p>unistd.h：提供通用的文件、目录、程序及进程操作的函数</p>
				<p>errno.h：提供错误号errno的定义，用于错误处理</p>
				<p>fcntl.h：提供对文件控制的函数</p>
				<p>time.h：提供有关时间的函数</p>
				<p>crypt.h：提供使用DES加密算法的加密函数</p>
				<p>pwd.h：提供对/etc/passwd文件访问的函数</p>
				<p>shadow.h：提供对/etc/shadow文件访问的函数</p>
				<p>pthread.h：提供多线程操作的函数</p>
				<p>signal.h：提供对信号操作的函数</p>
				<p>sys/wait.h、sys/ipc.h、sys/shm.h：提供进程等待、进程间通讯（IPC）及共享内存的函数</p>
				<p> </p>
		</font>
		<p>
				<font size="6">建议：</font>
				<font size="5">在编写网络程序时，可以直接使用下面这段头文件代码</font>
		</p>
		<font size="+2">
				<p>
						<font face="Times New Roman">#include &lt;unistd.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;sys/socket.h&gt;<br />#include &lt;netdb.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;ctype.h&gt;<br />#include &lt;errno.h&gt;<br />#include &lt;malloc.h&gt;<br />#include &lt;netinet/in.h&gt;<br />#include &lt;arpa/inet.h&gt;<br />#include &lt;sys/ioctl.h&gt;<br />#include &lt;stdarg.h&gt;<br />#include &lt;fcntl.h&gt;<br />#include &lt;fcntl.h&gt;<br />  </font>
				</p>
				<p>
				</p>
				<p>
						<b>涉及到用户权限及密码验证问题时加入如下语句：<br /></b>
						<font face="Times New Roman">#include &lt;shadow.h&gt;<br />#include &lt;crypt.h&gt;<br />#include &lt;pwd.h&gt;</font>
						<br />
						<font color="#ff0000">需要注意的是，应该在编译时链接加密算法库，即增加编译选项：<br />-lcrypt</font>
				</p>
				<p>　  </p>
				<p>
				</p>
				<p>
						<b>涉及到文件及时间操作加入如下语句：</b>
						<br />
						<font face="Times New Roman">#include &lt;sys/time.h&gt;<br />#include &lt;utime.h&gt;<br />#include &lt;time.h&gt;<br />#include &lt;sys/stat.h&gt;<br />#include &lt;sys/file.h&gt;<br />  </font>
				</p>
				<p>
				</p>
				<p>
						<b>涉及到多进程操作时加入如下语句：</b>
						<br />
						<font face="Times New Roman">#include &lt;sys/wait.h&gt;<br />#include &lt;sys/ipc.h&gt;<br />#include &lt;sys/shm.h&gt;<br />#include &lt;signal.h&gt;</font>
						<br />  </p>
				<p>
				</p>
				<p>
						<b>涉及到多线程操作时加入如下语句：</b>
						<br />
						<font face="Times New Roman">#include &lt;pthread.h&gt;<br />#include &lt;sys/poll.h&gt;<br /></font>
						<font color="#ff0000">需要注意的是，应该在编译时链接线程库，即增加编译选项：<br />-lthread</font>
				</p>
		</font>
<img src ="http://www.blogjava.net/huyi2006/aggbug/139176.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2007-08-24 20:54 <a href="http://www.blogjava.net/huyi2006/articles/139176.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux 下安装libpcap (库)手记 </title><link>http://www.blogjava.net/huyi2006/articles/127361.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Sun, 01 Jul 2007 07:47:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/127361.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/127361.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/127361.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/127361.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/127361.html</trackback:ping><description><![CDATA[
		<font size="2"> </font>
		<div>我最近开发个项目，要用到 libpcap 函数库，现将安装方法放在主页上供大家参考，</div>
		<div>
		</div>
		<div align="left">一 下载libpcap 库,文件的格式为x.tar.gz</div>
		<div align="left">      <a href="http://www.tcpdump.org/release/">http://www.tcpdump.org/release/</a></div>
		<div align="left">二 安装</div>
		<div align="left">     1、用 </div>
		<div align="left">          #tar zxvf x.tat.gz </div>
		<div align="left">          命令解压文件到你的当前目录</div>
		<div align="left">     2、进入刚才解开的libpcap目录，执行</div>
		<div align="left">          #./configure</div>
		<div align="left">          命令，生成Makefile文件</div>
		<div align="left">    3、输入 </div>
		<div align="left">          #make install</div>
		<div align="left">          将生成的库安装到系统默认目录中。此目录为 /usr/lib ，如果需要修改，可以修改文件Makefile 的 prefix。</div>
		<div align="left">    4、输入 </div>
		<div align="left">         #make install-incl </div>
		<div align="left">         将头文件安装至系统默认目录，/usr/include，修改同上</div>
		<div align="left">三 使用</div>
		<div align="left">          如果要使用libpcap,一般加入 </div>
		<div align="left">          #include &lt;pcap.h&gt;</div>
		<div>          编译选项： cc .. -lpcap –lsocket ..</div>
		<div> </div>
		<div>good luck </div>
		<div> </div>
<img src ="http://www.blogjava.net/huyi2006/aggbug/127361.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2007-07-01 15:47 <a href="http://www.blogjava.net/huyi2006/articles/127361.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IP首部检查和的理解</title><link>http://www.blogjava.net/huyi2006/articles/118178.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Thu, 17 May 2007 13:43:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/118178.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/118178.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/118178.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/118178.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/118178.html</trackback:ping><description><![CDATA[很多文章对ip首部检验和的计算介绍得很简略，在理解上常常会比较困难。这篇文章是我自己的一些理解。或许也有不正确的地方，希望大家指正。<br /><pre>这个问题一直困绕了我很长时间，今天终于理解了。 <br /><br /><br />我们可以通过spynet sniffer抓包软件，抓取一个ip数据包进行分析研究。 <br />下面我以本机抓到的一个完整的ip首部为例（红色字体表示）： <br /><br />0000: 00 e0 0f 7d 1e ba 00 13 8f 54 3b 70 08 00 45 00 <br />0010: 00 2e be 55 00 00 7a 11 51 ac de b7 7e e3 c0 a8 <br />0020: 12 7a <br /><br />45 00 00 2e----4表示ip版本号为ip第4版；5表示首部长度为5个32 bit字长，即为20字节；00 2e表示ip总长度为46字节，其中ip数据部分为 <br />26字节。 <br />be 55 00 00----be 55表示标识符；00 00表示3 bit标志及13 bit片偏移量； <br />7a 11 51 ac----7a表示ttl值为122；11表示协议号为17的udp协议；51 ac表示16 bit首部检验和值； <br />de b7 7e e3----表示32 bit 源ip地址为222.183.126.227 <br />c0 a8 12 7a----表示32 bit 目的ip地址为192.168.18.122 </pre><pre><br /><br /><br />检验和计算： <br />首先,把检验和字段置为0。 <br />45 00 00 2e <br />be 55 00 00 <br />7a 11 00 00&lt;----检验和置为0 <br />de b7 7e e3 <br />c0 a8 12 7a <br />其次，对整个首部中的每个16 bit进行二进制反码求和，求和值为3ae50，然后3+ae50=ae53（这是根据源代码中算法 cksum = (cksum <br />&gt;&gt; 16) + (cksum &amp; 0xffff) 进行的 ） <br /><br />最后，ae53+51ac=ffff。因此判断ip首部在传输过程中没有发生任何差错。</pre><img src ="http://www.blogjava.net/huyi2006/aggbug/118178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2007-05-17 21:43 <a href="http://www.blogjava.net/huyi2006/articles/118178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>