2011年5月

Python 编写 Server 端的步骤

第一步:创建 socket 对象

调用 socket 构造函数,如:

socket = socket.socket( family, type )
  • family 参数代表地址家族,可以为 AF_INET 或者 AF_UNIX ,AF_INET 家族包括 Internet 地址,AF_UNIX 家族则用于同一台机器上的进程间通信
  • type 参数代表套接字类型,可以为 SOCK_STREAM (流套接字) 或者 SOCK_DGRAM (数据报套接字)。

第二步:将 socket 绑定到指定地址

这是通过 socket 对象的 bind 方法来实现的:

socket.bind( address )

由 AF_INET 创建的套接字, address 必须是一个双元素无组,格式是 ( host, port ),host 代表主机, port 代表端口号,如果端与正在使用,主机名不正确或者商品端口已被保留, bind 方法将引发 socket.error 异常。

第三步:使用 listen 套接字的 listen 方法接收连接请求

socket.listen( backlog )

backlog 指定最多允许多少个客户连接到服务器,它的值至少为 1,收到连接请求后,这些请求需要排队,如果队列已满,就拒绝请求。

第四步:服务器套接字通过 socket 的 accept() 方法等待客户请求一个连接

connection, address = socket.accept()

调用 accept 方法时, socket 会进入 “waiting” 状态,客户请求连接时,方法建立连接并返回服务器, accept 方法返回一个含有两个元素的元组(connection, address),第一个元素 connection 是新的 socket 对象,服务器必须通过它与客户通信;第二个元素 address 是客户的 Internet 地址。

第五步:处理

服务器和客户端通过 send 和 recv 方法通信(传输数据)。服务器调用 send ,并采用字符串形式向客户发送信息,send 方法返回已发送的字符个数,服务器使用 recv 方法从客户端接收信息,调用 recv时,服务器必须指定一个整数,它对应于可通过本次方法调用来接收的最大数据量。 recv 方法在会进入“blocked”状态,最后返回一个字符串,用它表示接收到的数据,如果发送的数据量超过了 recv 所允许的数据会被截取,多余的数据将缓冲于接收端,以后调用 recv 时,多余的数据会从缓冲区删除(以及上次调用 recv 以来,客户可能发送的其它任何数据)。

第六步:传输结束

服务器调用 socket 的 close 方法关闭连接

Python 编写客户端的步骤

第一步:创建一个 socket 以连接服务器

socket = socket.socket( family, type)

第二步:使用 socket 的 connect 方法连接服务器

对于 AF_INET 家族,连接格式如下:

socket.connect(( host, port ))

host 代表服务器的主机名或者 IP, port 代表服务器进程所绑定的端口号,如果连接成功,客户端就可以与服务器进行通信了,如果连接失败,会引发 socket.error异常

第三步:处理阶段

客户和服务器将通过 send 方法和 recv 方法通信

第四步:传输结果

客房端通过 socket 的 close 方法关闭连接

整个示例的完整代码

server.py 文件

#!/usr/bin/env python
# encoding: utf-8
"""
File: server.py
Created by Pan Tao on 2011-09-20.
Copyright (c) 2011 CosTony.Com. All rights reserved.
"""
def main():
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8000))
sock.listen(5)
while True:
connection, address = sock.accept()
try:
connection.settimeout(5)
buf = connection.recv(1024)
if buf == '1':
print 'Client {} connected to server!'.format(address)
connection.send('Welcome to server!')
else:
connection.send('Please go out!')
except socket.timeout:
print 'Time out!'
connection.close()
if __name__ == '__main__':
main()

client.py 文件

#!/usr/bin/env python
# encoding: utf-8
"""
File: client.py
Created by Pan Tao on 2011-09-20.
Copyright (c) 2011 CosTony.Com. All rights reserved.
"""
def main():
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 8000))
import time
time.sleep(2)
sock.send('1')
print sock.recv(1024)
sock.close()
if __name__ == '__main__':
main()

测试运行

我们先运行 server.py 以开启服务器

python server.py

然后运行 client.py 连接服务器

python client.py

运行结果:

Server 端将打印出:

Client ('127.0.0.1', 56933) connected to server!

客户端将打印出:

Welcome to server!