使用 Python 进行 socket 编程
体验 Python
下面我们先对 Python 是什么建立一个直观印象。
作为一种解释性语言,Python 很容易使用,并且能够快速验证我们的想法和开发原型软件。Python 程序可以作为一个整体进行解释,也可以一行行地解释。
可以在第一次运行 Python 时测试一下下面的 Python 代码,然后一次只输入一行试试。在 Python 启动之后,会显示一个提示符(>>>),可以在这里输入命令。注意在 Python 中,缩进非常重要,因此代码前面的空格不能忽略:
清单 1. 可以试验的几个 Python 例子
# Open a file, read each line, and print it out for line in open('file.txt'): print line # Create a file and write to it file = open("test.txt", "w") file.write("test line\n") file.close() # Create a small dictionary of names and ages and manipulate family = {'Megan': 13, 'Elise': 8, 'Marc': 6} # results in 8 family['Elise'] # Remove the key/value pair del family['Elise'] # Create a list and a function that doubles its input. Map the # function to each of the elements of the list (creating a new # list as a result). arr = [1, 2, 3, 4, 5] def double(x): return x*x map(double, arr) # Create a class, inherit by another, and then instantiate it and # invoke its methods. class Simple: def __init__(self, name): self.name = name def hello(self): print self.name+" says hi." class Simple2(Simple): def goodbye(self): print self.name+" says goodbye." me = Simple2("Tim") me.hello() me.goodbye() |
为什么使用 Python?
我们要学习和使用 Python 的一个原因是它非常流行。Python 用户的数量以及使用 Python 编写的应用程序的不断增长使这种努力是值得的。
在很多开发领域中都可以看到 Python 的踪迹,它被用来构建系统工具,用作程序集成的黏合剂,用来开发Internet 应用程序和快速开发原型。
Python与其他脚本语言相比也有一定的优势。它的语法非常简单,概念非常清晰,这使得 Python 非常容易学习。在使用复杂的数据结构(例如列表、词典和元组)时,Python也非常简单,而且可描述性更好。Python 还可以对语言进行扩充,也可以由其他语言进行扩充。
我发现Python 的语法使它比 Perl 的可读性和可维护性更好,但是比 Ruby 要差。与 Ruby 相比,Python的优点在于它有大量的库和模块可以使用。使用这些库和模块,只需要很少的代码就可以开发功能丰富的程序。
Python使用缩进格式来判断代码的作用域,这有些讨厌,但是Python 本身的简单性使这个问题已经微不足道了。
现在,让我们开始进入 Python 中的 socket 编程世界。
Python socket 模块
基本的 Pythonsocket 模块
Python 提供了两个基本的 socket 模块。第一个是 <font face="Courier New">Socket</font>
,它提供了标准的BSD Sockets API。第二个是 <font face="Courier New">SocketServer</font>
,它提供了服务器中心类,可以简化网络服务器的开发。Python 使用一种异步的方式来实现这种功能,您可以提供一些插件类来处理服务器中应用程序特有的任务。表 1 列出了本节所涉及的类和模块。
表 1. Python 类和模块 | |
类/模块 | 说明 |
Socket | 低层网络接口(每个 BSD API) |
SocketServer | 提供简化网络服务器开发的类 |
让我们来看一下这些模块,以便理解它们是如何工作的。
Socket 模块
Socket模块提供了 UNIX? 程序员所熟悉的基本网络服务(也称为BSD API)。这个模块中提供了在构建 socket 服务器和客户机时所需要的所有功能。
这个API 与标准的 C API 之间的区别在于它是面向对象的。在C 中,socket 描述符是从 socket 调用中获得的,然后会作为一个参数传递给 BSD API 函数。在 Python 中,socket 方法会向应用 socket 方法的对象返回一个 socket 对象。表 2 给出了几个类方法,表 3 显示了一部分实例方法。
表 2. Socket 模块的类方法 | |
类方法 | 说明 |
Socket | 低层网络接口(每个 BSD API) |
socket.socket(family, type) | 创建并返回一个新的 socket 对象 |
socket.getfqdn(name) | 将使用点号分隔的 IP 地址字符串转换成一个完整的域名 |
socket.gethostbyname(hostname) | 将主机名解析为一个使用点号分隔的 IP 地址字符串 |
socket.fromfd(fd, family, type) | 从现有的文件描述符创建一个 socket 对象 |
表 3. Socket 模块的实例方法 | |
实例方法 | 说明 |
sock.bind( (adrs, port) ) | 将 socket 绑定到一个地址和端口上 |
sock.accept() | 返回一个客户机 socket(带有客户机端的地址信息) |
sock.listen(backlog) | 将 socket 设置成监听模式,能够监听 backlog 外来的连接请求 |
sock.connect( (adrs, port) ) | 将 socket 连接到定义的主机和端口上 |
sock.recv( buflen[, flags] ) | 从 socket 中接收数据,最多 buflen 个字符 |
sock.recvfrom( buflen[, flags] ) | 从 socket 中接收数据,最多 buflen 个字符,同时返回数据来源的远程主机和端口号 |
sock.send( data[, flags] ) | 通过 socket 发送数据 |
sock.sendto( data[, flags], addr ) | 通过 socket 发送数据 |
sock.close() | 关闭 socket |
sock.getsockopt( lvl, optname ) | 获得指定 socket 选项的值 |
sock.setsockopt( lvl, optname, val ) | 设置指定 socket 选项的值 |
类方法 和 实例方法 之间的区别在于,实例方法需要有一个 socket 实例(从 socket 返回)才能执行,而类方法则不需要。