调试是程序设计的一大难关,甚至难度超过编程本身,而网络应用程序由于具有异地性、多进程性、交互性等特点,更难于用普通的调试工具查找逻辑错误。特别是开发基于Client/Server结构的网络应用时,进行程序跟踪、中断输出等传统的调试手段都难以确切找出错误所在。本人在开发类似Zmud的MUD客户端程序时,就曾经因为一个字符回显错误而调试了四五个小时。
---- 如果开发一种类似管道一样的网络中间程序,将客户方和服务方的通讯过程依次记录下来,然后进行离线分析,则往往会收到事半功倍的效果。
---- 程序结构很简单,仅由两个进程组成,后台启动后驻留等待连接。父进程监听本地预定的临时端口,收到客户方请求后向服务方发连接请求,连接建立后生成子进程,自身负责接收客户方输出并传送给服务方;子进程继承父进程的Socket描述符,负责接收服务方输出并传送给客户方。整体结构如下图:(略)
---- 程序在完成通讯的同时将双方的通讯内容记录在工作目录的预定文件中,并冠以Client 和Server的前缀,以区分不同的信息源。值得注意的是,标准I/O库函数是缓冲输出的,不能记录通讯的顺序,必须使用原始I/O(read/write)
---- 结果文件以字节为单位进行记录,包括传输的ASCII码和相应的可显示字符。以编写处理Telnet的程序为例,为了了解Telnet协议中建立登录连接以前的协商过程,可以使用本程序。
---- 假设本程序的可执行文件名为netpipe,本地IP为172.10.33.28,远地Telnet服务器IP为172.20.8.144,程序预先指定监听本地端口8888。首先运行netpipe,然后运行Telnet :
$netpipe 172.20.8.144 23&
$telnet 172.10.33.28 8888
.
.
.
Ctrl-D
省缺的记录文件将如下显示:
Server :
255
253
24
255
253
32
255
253
35 #
255
253
39 '
Client :
255
251
.
.
.
---- 在外观上本次Telnet会晤与直接Telnet没有任何区别,唯一不同的就是本次通讯将生成一个记录文件。本程序在Linux Kernel 2.2.5下用gcc 2.3编译通过,可方便地移植到不同系统,包括Windows 95/NT。