第1页: 前言
第2页:课堂Windows打印管理在Linux平台实现
本文介绍了一种在Linux平台上实现Windows打印机管理的移植方法及具体实现细节。通过本文,读者可以了解相关技术,并把这些技术直接应用到实际软件开发中。
1.理解Windows打印机管理和Linux打印机管理
Windows平台提供了非常简单而且完善的打印机管理系统。在Windows编程中,打印功能被融入了GDI (Graphic Device Interface)模块。在GDI模块中,程序员只要调用EnumPrinters()等APIs就可以轻松获取打印机信息。
Windows的这种成熟打印管理机制很大程度上得益于打印机供应商所提供的完善的打印机驱动。Windows的打印机驱动屏蔽了打印机的具体打印实现细节,同时为上层调用提供了简单的API接口。
与Windows平台相反,打印机管理机制在Linux平台上从产生到成熟却经过了一个漫长的过程。Linux打印系统最早源于UNIX打印系统,但UNIX系统却一直缺乏统一的标准接口。由于历史原因,不同UNIX平台使用着不同的打印系统。在各种UNIX打印解决方案中,最流行的是Berkeley打印系统和System V打印系统。 一方面,不同打印系统需要不一样的打印驱动支持;另一方面,UNIX只拥有相对较小的客户群。这些因素使得很多打印机供应商完全放弃了对UNIX平台的支持。统一打印接口的缺乏和底层驱动的不完善使打印在很长一段时间内成为了Linux平台的一大功能漏洞。
最终CUPS (Common UNIX Printing System)的出现解决了上述窘境。CUPS是UNIX/Linux上通用的打印系统。CUPS提供了一套CUPS API来完成UNIX/Linux系统和打印机之间的交互。
例如,用户可以通过CUPS获取打印机的信息,也可以通过CUPS设置打印机。CUPS提供了对Berkeley和System V打印命令的支持,这种兼容性使得之前的系统不用进行大规模修改就可被延续使用。
同时,CUPS还提供一系列模块化的过滤接口。通过这些接口,打印机提供商只需要开发一个驱动程序就可以满足所有平台的需求。至今为止,CUPS已被所有UNIX和Linux平台所支持。
2.打印机管理移植架构
打印机管理移植是应用程序跨平台移植的重要组成部分。不同平台所支持的打印接口是不同的,因此移植的核心就是实现平台之间的打印机管理接口的转换。下图展示了打印机管理移植的架构。
图1打印机管理移植架构
Windows提供了一系列API来获取打印机信息。这些信息被封装在预定义的Windows标准结构中,比如DEVMODE,PRINTER_INFO_2,PRINTER_INFO_4等等。
Linux使用CUPS来获取打印机信息,这些信息被封装在cups_dest_t,ipp_attribute_t等数据结构中。只要正确获取Linux平台上打印机信息,并把它们转化成Windows打印机数据结构,就可以完成打印机管理。
3.CUPS基础知识
CUPS是UNIX/Linux平台上的打印系统。CUPS的定义和实现是基于IPP(Internet Printing Protocol)协议的。IPP是通用的打印系统标准,它的功能和操作被一系列RFC(Request for Comments)所详细定义。这些具体功能和操作包括:建立IPP请求,应答IPP请求和设置IPP请求等等。
和IPP相关的RFC包括RFC1179,RFC2910,RFC2911,RFC3196等等。在网络协议中,IPP位于HTTP(Hyper-Text Transport Protocol)协议之上。因此以下代码示例将涉及到很多IPP和HTTP的系统调用,例如ippAddString()和httpConnectEncrypt()等等。此外,在UNIX/Linux平台上在使用CUPS之前要提前引入下列头文件:
#include #include #include #include
有了上述CUPS基础知识,下文将举例说明使用CUPS实现打印机管理移植的技术细节。
4.获取打印机数量
Windows通过API EnumPrinters()的返回参数pcReturned来获取系统的打印机数量。Windows程序的具体实现如下所示:
int n_PrinterCount;EnumPrinters( , , , , , , &n_PrinterCount);
在Linux中,CUPS函数cupsGetDests()可实现同样的功能。需要注意的是,在调用结束后,调用者需要使用cupsFreeDests()来释放内存。
cups_dest_t *dests; int n_PrinterCount = cupsGetDests( &dests ); cupsFreeDests(count, dests);
5.获取打印机名称,打印机端口和打印机型号
Windows使用API EnumPrinters()来获取打印机名称,打印机端口和打印机型号。详情请参考Windows MSDN。在Linux平台上,CUPS可实现同样的功能。具体实现流程如下图所示:
图2获取打印机信息(名称,端口,型号)流程
5.1建立HTTP连接
使用CUPS获取打印机名称,打印机端口和打印机型号信息首先需要开启IPP和HTTP服务。开启服务的第一步是建立一个HTTP连接来和CUPS服务器取得联系。在下面的代码中,cupsServer()将返回指向默认CUPS服务器名称的指针;ippPort()将返回IPP请求的默认端口号;cupsEncryption()将返回当前CUPS请求的默认加密设置。