4.编写客户端
客户端代码Client.py,和Server.py非常相似。下面是完整的代码:
import sys, traceback, Ice import Demo status = 0 ic = None try: ic = Ice.initialize(sys.argv) base = ic.stringToProxy("SimplePrinter:default -p 10000") printer = Demo.PrinterPrx.checkedCast(base) if not printer: raise RuntimeError("Invalid proxy") printer.printString("Hello World!") except: traceback.print_exc() status = 1 if ic: # Clean up try: ic.destroy() except: traceback.print_exc() status = 1 sys.exit(status) |
注意这里的代码结构和服务器是一样的。我们使用同样的try 和except来处理错误。try 块的代码执行顺序如下:
1)和在服务器中一样,我们调用Ice::initialize初始化Ice run time。
2)下一步是取得远程打印机的代理。我们通过在communicator上调用stringToProxy创建一个代理,它带有一个字符串参数“SimplePrinter:default -p 10000”,这个字符串里包含了服务器中用到的对象标识符和端口号(当然,在程序代码里直接对对象标识符和端口号进行硬性编码确实是个不好的做法,但现在我们先这样做,以后在手册的33章节可以看到在代码结构更好的方法)
3)stringToProxy返回的代理类型时Ice::ObjectPrx,这种类型是接口和类的继承树上的根节点。但是说到我们实际用的printer,我们要的是Demo::Print,而不是一个Object接口的代理。为此,我们要调用Demo.PrinterPrx.checkedCast进行向下转换,这个checked方法会发送一条消息给服务器,并询问:“这是一个Demo::Printer接口的代理吗?”,如果是,这个调用会返回一个Demo.PrintPrx类型的代理;否则,如果代理表示是其他的类型,这个调用会返回None。
4)我们测试向下转型是否成功,如果不成功,就抛出错误消息,中止。
5)好了,现在我们在我们的地址空间里有个活动的代理(应该是有生命周期的意思),可以调用printString方法,把"Hello World!"字符串传递给它,服务器就会在终端上打印这个字符串。
5.运行客户端和服务器
运行客户端和服务器之前,我们先在一个单独的窗口启动服务器:
$python Server.py |
这时,我们看不到任何东西,因为服务器只是简单地等待客户和它连接。
我们在另一个窗口运行客户端:
$python Client.py |
客户端运行之后退出,并不产生任何输出结果,但在服务器窗口中,我们会看到"Hello World!" 。要终止服务器,我们目前的做法是直接在命令行上中断它。