课堂Windows打印管理在Linux平台实现
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 请求的默认加密设置。
将这些返回值作为参数传递给函数 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);