首页 | 邮件资讯 | 技术教程 | 解决方案 | 产品评测 | 邮件人才 | 邮件博客 | 邮件系统论坛 | 软件下载 | 邮件周刊 | 热点专题 | 工具
网络技术 | 操作系统 | 邮件系统 | 客户端 | 电子邮箱 | 反垃圾邮件 | 邮件安全 | 邮件营销 | 移动电邮 | 邮件软件下载 | 电子书下载

操作系统

Windows 9X | Linux&Uinx | Windows Server | 其它操作系统 | Vista | FreeBSD | Windows 7 |
首页 > 操作系统 > Linux&Uinx > Windows 打印管理在Linux 平台实现 > 正文

Windows 打印管理在Linux 平台实现

出处:5DMail.Net收集整理 作者:请作者联系 时间:2006-11-18 12:20:00

    本文介绍了一种在 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 打印机管理移植架构
图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 <cups/cups.h>#include <cups/language.h>#include <cups/http.h>#include <cups/ipp.h>


    有了上述 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 获取打印机信息(名称,端口,型号)流程
图2  获取打印机信息(名称,端口,型号)流程

5.1建立 HTTP 连接

    使用 CUPS 获取打印机名称,打印机端口和打印机型号信息首先需要开启 IPP 和HTTP 服务。开启服务的第一步是建立一个 HTTP 连接来和 CUPS 服务器取得联系。在下面的代码中,cupsServer() 将返回指向默认 CUPS 服务器名称的指针;ippPort() 将返回 IPP 请求的默认端口号;cupsEncryption() 将返回当前 CUPS 请求的默认加密设置。将这些返回值作为参数传递给函数 httpConnectEncrypt() 就可以建立一个 HTTP 连接。如果 HTTP 连接建立成功,即 httpConnectEncrypt() 的返回值pHTTPConnection 有效,那么就可以基于这个连接进行下一步 IPP 请求。


        http_t *pHTTPConnection = httpConnectEncrypt( cupsServer(),                                             ippPort(),                                             cupsEncryption() );    if (!pHTTPConnection)    {        g_print("Cannot connect to CUPS server\n");        return 0;    }    


5.2建立 IPP 请求

    建立一个新的 IPP 请求是通过 IPP 调用 ippNew() 来实现的。在此,operation_id 被设置为 CUPS_GET_PRINTERS,其语义是当前 IPP 请求要获取和打印机相关的信息。同时,request_id 被设置为 1,这是 IPP 协议所规定的。


        ipp_t *pIPPReq = ippNew();    pIPPReq->request.op.operation_id = CUPS_GET_PRINTERS;    pIPPReq->request.op.request_id = 1;

5.3设置 IPP 请求

    以下是进一步设置当前 IPP 请求 pIPPReq 的细节。需要指出的是,在和 CUPS 服务器进行交互的过程中,很多信息是通过字符串来传递的。这就涉及到了文字语言编码表示的问题。函数 cupsLangDefault() 就是用来获取 CUPS 服务器的默认语言设置。cupsLangDefault() 的返回值 pDefLang 还将作为参数传递给其它函数来完成对 IPP 请求的进一步设置。

    根据 IPP 协议,对 IPP 请求的设置要从设置参数 "attributes-charset"(字符集)和"attributes-natural-language"(自然语言)开始。下列代码分别用系统默认字符集和CUPS 默认语言来设置这两个参数。完成这两项规定设置后,用户就可以根据需求对需要的信息提出请求。此处需要获得的信息是打印机名称,端口号和打印机型号。在 IPP 协议中,这三项对应的IPP请求关键字分别是 "printer-name", "device-uri" 和 "printer-make-and-model"。下列代码定义了数组 pReqAttrs 来存储上述关键字,然后通过请求参数 "requested-attributes" 来设置这些 IPP 请求。


                      cups_lang_t *pDefLang = cupsLangDefault();    if (!pDefLang)    {        g_print("Cannot get default language\n");        return 0;    }    ippAddString(pIPPReq,                 IPP_TAG_OPERATION,                 IPP_TAG_CHARSET,                 "attributes-charset",                 NULL,                 cupsLangEncoding(pDefLang));    ippAddString(pIPPReq,                 IPP_TAG_OPERATION,                 IPP_TAG_LANGUAGE,                 "attributes-natural-language",                 NULL,                 pDefLang->language);static const char *pReqAttrs[] = {"printer-name", "device-uri","printer-make-and-model"};    ippAddStrings(pIPPReq,                  IPP_TAG_OPERATION,                  IPP_TAG_KEYWORD,                  "requested-attributes",                  3,                     NULL,                  pReqAttrs);                  


5.4发送 IPP 请求

    设置好 IPP 请求之后,通过函数 cupsDoRequest() 就可以把指定IPP请求发送到服务器端。如果请求发送成功,那么请求发送方将得到有效的IPP应答pIPPRes。需要指出的是,即使 IPP 应答有效,也并不意味着所有 IPP 请求的内容都得到了正确的回复。还需要进一步检查 IPP 应答的状态代码 "request.status.status_code" 来核实反馈信息的有效性。


        ipp_t *pIPPRes = cupsDoRequest(pHTTPConnection, pIPPReq, "/");    if (!pIPPRes)    {        g_print("No response from CUPS server\n");        return 0;    }    if (pIPPRes->request.status.status_code > IPP_OK_CONFLICT)    {        printf("IPP Error: %s\n", ippErrorString(pIPPRes->request.status.status_code));        ippDelete(pIPPRes);        return 0;    }    

5.5获取 IPP 应答

    如果上述操作都成功返回,就可以进一步从 pIPPRes 结构中提取感兴趣的信息。在下列代码中,变量 pPrinterName,pPortName 和 pPrinterModel 分别用来存储打印机名称,打印机端口号和打印机的类型信息。通过依次枚举 IPP 应答 pIPPRes 来寻找属性 pAttr->name 为 "printer-name" 或 "device-uri" 或 "printer-make-and-model" 的分量,就可以得到上述信息。


        char *pPrinterName = NULL;    char *pPortName = NULL;    char *pPrinterModel = NULL;    for (ipp_attribute_t *pAttr = pIPPRes->attrs; pAttr != NULL; pAttr =	pAttr->next)    {        if (pAttr->group_tag == IPP_TAG_PRINTER)        {            if (0 == strcmp(pAttr->name, "printer-name"))                pPrinterName = pAttr->values->string.text;            if (0 == strcmp(pAttr->name, "device-uri"))                pPortName = pAttr->values->string.text;            if (0 == strcmp(pAttr->name, "printer-make-and-model"))                pPrinterModel = pAttr->values->string.text;        }    }    


5.6释放内存

    最后,需要释放相关内存以免内存泄露:


        httpClose(pHTTPConnection);    ippDelete(pIPPRes);    


6字符编码转换

    在实现打印机管理的移植过程中,还需要特别注意字符编码转换的问题。当然,字符编码问题不仅仅局限于本文所探讨的范畴,它同时还是所有应用程序移植都需要特别关注的技术细节。以本文为例,在 Linux 上获取的字符串,比如打印机名称,通常是 UTF-8(Unicode Transformation Format) 编码的。而 Windows 应用程序并不使用 UTF-8 编码。由于历史原因,Windows 程序或使用 ANSI 编码方式,或使用UTF-16 编码方式。因此,从 CUPS 获取的字符串还需要根据程序运行环境进行编码转换,之后才能被 Windows 应用程序使用。字符编码转换可以使用 IBM ICU(International Components for Unicode)来完成。详情请参考 http://www-306.ibm.com/software/globalization/icu/index.jsp

7.结束语

    移植是一项实现应用程序跨平台运行的核心技术。本文重点阐述了 Windows 打印机管理系统在 Linux 平台上的移植技术。通过具体举例,本文详细分析了打印机管理在 Linux 平台上的移植细节。本章涉及的移植架构和移植概念不仅仅局限于打印机管理移植。这些概念和思想也是所有应用程序所通用的。应用程序跨平台移植已经在很多软件中被应用。实现应用程序在不同平台上无缝隙的运行操作也将是每位移植技术人员的共同目标。



 

参考资料

  1. "CUPS Software Programmers Manual", Easy Software Products, Copyright 1997-2004
  2. "CUPS Implementation of IPP", Easy Software Products, Copyright 1997-2004
  3. RFC2910 "Internet Printing Protocol/1.1: Encoding and Transport", 2000
  4. RFC2911 "Internet Printing Protocol/1.1: Model and Semantics", 2000
  5. RFC3196 "Internet Printing Protocol/1.1: Implementor's Guide", 2001
  6. MSDN: Microsoft Developer Network
  7. http://www-306.ibm.com/software/globalization/icu/index.jsp
相关文章 热门文章
  • 微软宣布已售出4亿份Windows 7许可
  • Powercfg 从命令行控制系统的电源管理
  • windows NT 4.0 Domain升级到windows server 2008 R2需要注意的几个问题
  • windows 7使用GPO统一桌面黑屏
  • Windows server 2008 R2上安装exchange 2010注意的问题
  • 利用Windows Server Backup备份Exchange 2010 DAG
  • 恢复安装在Windows 2008域控制器上的Exchange 2010
  • Windows 2003域更名工具(Domain Rename Tool)
  • 创建Windows 7部署介质
  • 轻松传送——Windows Easy Transfer
  • 使用MDT 2010执行Windows 7裸机安装
  • 限制Windows管理员账户的并发登录
  • linux的基本操作(上)
  • Linux系统下应用知识大荟萃
  • GNU GRUB启动管理器
  • 制作基于软盘的Linux系统
  • 网络配置文件快速解读
  • linux的基本操作(下)
  • 剖析Linux系统启动过程
  • DameWare让局域网管理不再繁琐
  • 在Redhat 9下实现双机热备和集群功能
  • LINUX守护进程介绍
  • Redhat advance server 2.1集群的安装与管理
  • Linux必须学会的60个命令-文件处理
  • 自由广告区
     
    最新软件下载
  • SharePoint Server 2010 部署文档
  • Exchange 2010 RTM升级至SP1 教程
  • Exchange 2010 OWA下RBAC实现的组功能...
  • Lync Server 2010 Standard Edition 标..
  • Lync Server 2010 Enterprise Edition...
  • Forefront Endpoint Protection 2010 ...
  • Lync Server 2010 Edge 服务器部署文档
  • 《Exchange 2003专家指南》
  • Mastering Hyper-V Deployment
  • Windows Server 2008 R2 Hyper-V
  • Microsoft Lync Server 2010 Unleashed
  • Windows Server 2008 R2 Unleashed
  • 今日邮件技术文章
  • 腾讯,在创新中演绎互联网“进化论”
  • 华科人 张小龙 (中国第二代程序员 QQ...
  • 微软推出新功能 提高Hotmail密码安全性
  • 快压技巧分享:秒传邮件超大附件
  • 不容忽视的邮件营销数据分析过程中的算..
  • 国内手机邮箱的现状与未来发展——访尚..
  • 易观数据:2011Q2中国手机邮箱市场收入..
  • 穿越时空的爱恋 QQ邮箱音视频及贺卡邮件
  • Hotmail新功能:“我的朋友可能被黑了”
  • 入侵邻居网络发骚扰邮件 美国男子被重..
  • 网易邮箱莫子睿:《非你莫属》招聘多过..
  • 中国电信推广189邮箱绿色账单
  • 最新专题
  • 鸟哥的Linux私房菜之Mail服务器
  • Exchange Server 2010技术专题
  • Windows 7 技术专题
  • Sendmail 邮件系统配置
  • 组建Exchange 2003邮件系统
  • Windows Server 2008 专题
  • ORF 反垃圾邮件系统
  • Exchange Server 2007 专题
  • ISA Server 2006 教程专题
  • Windows Vista 技术专题
  • “黑莓”(BlackBerry)专题
  • Apache James 专题
  • 分类导航
    邮件新闻资讯:
    IT业界 | 邮件服务器 | 邮件趣闻 | 移动电邮
    电子邮箱 | 反垃圾邮件|邮件客户端|网络安全
    行业数据 | 邮件人物 | 网站公告 | 行业法规
    网络技术:
    邮件原理 | 网络协议 | 网络管理 | 传输介质
    线路接入 | 路由接口 | 邮件存储 | 华为3Com
    CISCO技术 | 网络与服务器硬件
    操作系统:
    Windows 9X | Linux&Uinx | Windows NT
    Windows Vista | FreeBSD | 其它操作系统
    邮件服务器:
    程序与开发 | Exchange | Qmail | Postfix
    Sendmail | MDaemon | Domino | Foxmail
    KerioMail | JavaMail | Winwebmail |James
    Merak&VisNetic | CMailServer | WinMail
    金笛邮件系统 | 其它 |
    反垃圾邮件:
    综述| 客户端反垃圾邮件|服务器端反垃圾邮件
    邮件客户端软件:
    Outlook | Foxmail | DreamMail| KooMail
    The bat | 雷鸟 | Eudora |Becky! |Pegasus
    IncrediMail |其它
    电子邮箱: 个人邮箱 | 企业邮箱 |Gmail
    移动电子邮件:服务器 | 客户端 | 技术前沿
    邮件网络安全:
    软件漏洞 | 安全知识 | 病毒公告 |防火墙
    攻防技术 | 病毒查杀| ISA | 数字签名
    邮件营销:
    Email营销 | 网络营销 | 营销技巧 |营销案例
    邮件人才:招聘 | 职场 | 培训 | 指南 | 职场
    解决方案:
    邮件系统|反垃圾邮件 |安全 |移动电邮 |招标
    产品评测:
    邮件系统 |反垃圾邮件 |邮箱 |安全 |客户端
    广告联系 | 合作联系 | 关于我们 | 联系我们 | 繁體中文
    版权所有:邮件技术资讯网©2003-2010 www.5dmail.net, All Rights Reserved
    www.5Dmail.net Web Team   粤ICP备05009143号