16.3 Python中的网络编程
16.3.1 socket()模块函数
使用socket.socket()函数来创建套接字。
socket(socket_family, socket_type, protocol = 0)
>>> import socket
>>> tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>>
16.3.3 创建一个TCP服务器
所有的套接字都用socket.socket()函数来创建。服务器需要"坐在某个端口上"等待请求。所以它们必需要“绑定”到一个本地的地址上。由于TCP是一个面向连接的通信系统,在TCP服务器可以开始工作之前,要先完成一些设置。TCP服务器必须“监听”(进来的)连接,设置完成之后,服务器就可以进入无限循环了。
一个简单的(单线程的)服务器会调用accept()函数等待连接的到来。默认情况下,accept()函数是阻塞式的,即程序在连接到来之前会处于挂起状态。套接字也支持非阻塞模式。
一旦接收到一个连接,accept()函数就会返回一个单独的客户端套接字用于后续的通信。使用新的客户端套接字就像把客户的电话转给一个客户服务人员。
在临时套接字创建好之后,通信就可以开始了。客户与服务器都使用这个新创建的套接字进行数据的发送与接收,直到通讯的某一方关闭了连接或发送了一个空字符串之后,通讯就结束了。
在设计一个更智能的退出方案时,比方说,服务器被通知要关闭时,要确保close()函数会被调用。
from socket import *
from time import ctime
HOST = ''
PORT = 12345
BUFSIZ = 1024 #Cache size is 1k
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
while True:
print 'Waiting for connection...'
tcpCliSock, addr = tcpSerSock.accept()
print '...Connected from:', addr
while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send('[%s] %s' % (ctime(), data))
tcpCliSock.close()
tcpSerSock.close()
16.3.4 创建TCP客户端
所有的套接字都由socket.socket()函数创建。在客户端有了套接字之后,马上就可以调用connect()函数去连接服务器。连接建立后,就可以与服务器开始对话了。在对话结束后,客户端就可以关闭套接字,结束连接。
from socket import *
HOST = 'localhost'
PORT = 12345
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data = raw_input('> ')
if not data:
break
tcpCliSock.send(data)
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print data
tcpCliSock.close()
16.3.5 运行我们的客户端与TCP服务器
服务器是一个被动端,它先创建自己然后被动地等待连接。而客户端则是主动端,由它主动建立一个连接。
要先开服务器,后开客户端。