一个类似的样例程序,稍做修改就可实现这个功能。这个程序也可以集成在minitcpip中实现。
minitcpip使用了其中第三种解决办法,网卡必须设置在混杂模式。这样在网络负载大的场合,CPU占用率会比较高,丢包的概率会增加,效率会下降。因此minitcpip只适用于小负载的场合。
有协议简介
minitcpip向客户端提供的服务采用了C/S模型,这个服务的模型图如前图2所示,关于其细节请参见《UNIX环境高级编程》。任何用户的应用进程对minitcpip的使用必须通过minisocket函数库进行,而minisocket与minitcpip之间则通过一个自定义的私有协议进行。这个私有协议实现在用户进程与协议软件进程之间利用命名管道建立的C/S通讯中。
命名管道已经是可靠的本地进程间通讯机制,然而minisocket与minitcpip协议软件之间传递的不仅仅是发送与接收的字节流,还包括对SOCKET的控制,比如申请SOCKET号,建立TCP连接、关闭TCP连接等控制命令,所以必须设计一个简单的通讯协议来满足具体的通讯要求。详细的通讯协议的规格说明这里不再列出。
管道通讯一般不会发生数据包的丢失和错序问题,所以该协议实质上只需要负责包的捡出(利用转义和数据长度和校验和)和分辨不同种类的数据包(信息包、控制包)。若管道操作本身出现错误,则程序异常退出。下图5是这个私有协议使用的数据报格式:具体的数据包的检出与字符填充方案等由于与本文主题关系不大,这里不再详述。
其中,数据域的第一个字节总是命令类型,顾名思义,命令类型定义了应用程序与协议软件之间所有的通讯数据的类型,主要包括两类命令,即控制命令和信息传输命令,控制命令用来控制TCP连接的状态等,信息命令则是客户机真正要传输的数据或服务器收到的回发给客户机的数据。具体的命令格式列表不再详述。
minisocket用户编程接口与例程
客户机通过调用minisocket接口与minitcpip通讯,这个接口封装了私有协议繁琐的细节,提供了类似与标准SOCKET接口的简单统一的函数库给用户使用。目前实现的minisocket接口函数库还相当简单,功能也很有限,只包括TCP协议客户端的实现。在编写客户端应用程序时,用户只需要知道少数几个数据结构和函数原型就可以了:
struct mini_sock{ u8 type;//=TCP or UDP u32 dip;//destination ip u32 dport;//destination port u16 sip;//source ip u16 sport;//source port …… } 该数据结构定义在mini_socket.h中,包含了用户需要建立的TCP连接的所有参数 用户函数接口定义: int mini_socket(struct mini_sock*) 该函数创建一个SOCKET,struct socket*中必须正确填写欲创建的SOCKET有关的参数。 成功的返回值实际上是协议软件写入数据的客户机专用FIFO文件描述符。这样用户可以使用标准的select()函数实现单进程的多个输入输出的处理。但是在这个文件描述符上的读写操作必须使用minisocket提供的函数才能正确进行。 int mini_connect(int socket) 该函数用来通知协议软件通过与目标主机三次握手后,建立TCP连接 int mini_recv(int socket, char* buf,int * buflen) 该函数从指定的SOCKET接收数据 int mini_send(int socket,char*buf,int buflen) 该函数将指定的数据发送到SOCKET int mini_close(int socket) 该函数用来通知协议软件关闭指定的socket连接 使用本协议软件库函数实现ECHO服务的一个简单例程如下: /*************************************************** * Simple tcp echo client using libnet and libpcap and mini_socket.c * file: miniecho.c * Date: 2003.5. * Author: white cpf * compile: gcc -Wall -lpcap -lnet miniecho.c mini_socket.c -o miniecho * Run: readhat 8.0 you must be root and run ifconfig to see eth0 OK *****************************************************/ #include
结论
本文通过使用目前广泛流行的libnet和libpcap函数库,在Linux环境下实现了一个单进程的TCP/IP协议软件:minitcpip,并且提供了一个调用接口:minisocket,通过这个接口,可以创建基于TCP/IP协议的应用程序。
本文实现的minitcpip协议软件只具有最小的TCP/IP通讯功能,效率也非常一般。但是,作为一个学习libnet、libpcap,学习TCP/IP软件在以太网上的实现原理的目的,这个项目却具有一定的价值。另外,采用这种方案实现的协议与libnet、libpcap、操作系统之间的层次关系清晰,可以想象,minisocket中与环境无关的代码可以很容易的移植到目前越来越广泛使用的嵌入式设备的网络应用上,这是作者写作本文的又一个考虑。
由于时间紧张,minitcpip协议软件的实现方法许多都有继续斟酌之处,而且作者本身也在学习过程中,错误之处在所难免,本文若能为大家学习libnet、libpcap、tcpip有所帮助,作者欣慰之至。同时希望大家能给出批评和指正,以利共同提高。
参考资料
? ? ?
www.tcpdump.org
www.packetfactory.net/libnet
《UNIX环境高级编程》 机械工业出版社 2000年2月 W.Richard Stevens
著
《用TCP/IP进行网际互连 第二卷:设计、实现和内部构成》第2版 电子
工业出版社 1998年 DOUGLES E.COMER DAVID L.STEVENS著
《一个TCP调试系统的设计与实现》 章淼 熊勇强 吴建平 清华大学计算
机系网络研究所
?
?