SocketServer 模块
SocketServer模块是一个十分有用的模块,它可以简化 socket 服务器的开发。有关这个模块的使用的讨论已经远远超出了本教程的范围,但是我将展示一下它的基本用法,然后您可以参阅参考资料 一节中给出的链接。
考虑清单2 中给出的例子。此处,我们实现了一个简单的 “Hello World” 服务器,当客户机连接它时,它就会显示这样一条消息。我首先创建一个请求处理程序,它继承了 SocketServer.StreamRequestHandler 类。我们定义了一个名为 handle 的方法,它处理服务器的请求。服务器所做的每件事情都必须在这个函数的上下文中进行处理(最后,关闭这个 socket)。这个过程的工作方式非常简单,但是您可以使用这个类来实现一个简单的HTTP 服务器。在 handle 方法中,我们打一个招呼就退出了。
现在连接处理程序已经准备就绪了,剩下的工作是创建 socket 服务器。我们使用了 SocketServer.TCPServer 类,并提供了地址和端口号(要将服务器绑定到哪个端口上)以及请求处理方法。结果是一个 TCPServer 对象。调用 serve_forever 方法启动服务器,并使其对这个连接可用。
清单2. 用 SocketServer 模块实现一个简单的服务器
import SocketServer
class hwRequestHandler( SocketServer.StreamRequestHandler ):
def handle( self ):
self.wfile.write("Hello World!\n")
server = SocketServer.TCPServer( ("", 2525), hwRequestHandler )
server.serve_forever()
就是这样!Python 允许这种机制的任何变种,包括 UDPServers 以及派生进程和线程的服务器。请参阅 参考资料一节中更多信息的链接。
在所有具有 socket 的语言中,socket 都是相同的 —— 这是两个应用程序彼此进行通信的管道。
前提条件
不管是使用 Python、Perl、Ruby、Scheme 还是其他有用的语言(此处 有用 的意思是这种语言有socket 接口)来编写 socket 程序,socket 通常都是相同的。这是两个应用程序彼此进行通信的管道(这两个应用程序可以在同一台机器上,也可以位于两台不同的机器上)。
使用Python 这种具有 socket 编程功能的语言的区别在于,它有一些辅助的类和方法,可以简化 socket 编程。在本节中,我们将展示 Python 的 socket API。可以使用一个脚本来执行 Python 的解释器,如果您要自己执行 Python,就可以一次只输入一行代码。这样,就可以看到每个方法调用之后的结果了。
下面这个例子展示了如何与 Python 解释器进行交互。此处我们使用了 socket 类方法 gethostbyname 将一个完整的域名()解析成一个使用点号分隔的 IP 地址字符串('129.42.19.99'):
清单 3. 从解释器命令行中使用 socket
[camus]$ python
Python 2.4 (#1, Feb 20 2005, 11:25:45)
[GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)] on linux2
Type "help", "copyright", "credits" or "license" for more
information.
>>> import socket
>>> socket.gethostbyname('www.ibm.com')
'129.42.19.99'
>>>
在导入 socket 模块之后,我调用了 gethostbyname 类方法将这个域名解析成 IP 地址。
现在,我们要讨论基本的 socket 方法,并通过 socket 进行通信。您应该熟悉 Python 解释器。
创建和销毁 socket
要新创建一个 socket,可以使用 socket 类的 socket 方法。这是一个类方法,因为还没有得到可以应用方法的socket 对象。socket 方法与BSD API 类似,下面是创建流(TCP) socket 和数据报(UDP)socket 的方法:
清单 4. 创建流和数据报 socket
streamSock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
dgramSock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
在这种情况中,会返回一个 socket 对象。AF_INET 符号(第一个参数)说明您正在请求的是一个 Internet 协议(IP)socket,具体来说是 IPv4。第二个参数是传输协议的类型(SOCK_STREAM 对应TCP socket,SOCK_DGRAM 对应 UDP socket)。如果底层操作系统支持 IPv6,那么还可以指定 socket.AF_INET6 来创建一个 IPv6 socket。
要关闭一个已经连接的 socket,可以使用 close 方法:
streamSock.close()
最后,可以使用 del 语句删除一个 socket:
del streamSock
这个语句可以永久地删除 socket 对象。之后再试图引用这个对象就会产生错误。