socket模块中用于创建套接字的函数是socket(),语法是
socket(socket_family,socket_type,protocol=0)
socket_family可以是AF_UNIX或是AF_INET,socket_type可以是SOCK_STREAM或是SOCK_DGRAM,protocol一般情况下是不填的,默认为 0.
创建TCP/IP套接字 tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
创建UDP/IP套接字 udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
通过调用socket.socket()创建一个套接字对象,之后的交互都可以通过调用这个套接字对象的方法来进行。
现在列一些套接字对象常用的方法
服务器端套接字方法
s.bind() 绑定地址到套接字对象,地址为主机、端口对
s.listen() 监听端口
s.accept() 被动的阻塞式的接受连接
客户端套接字方法
s.connect() 初始化连接
s.connect_ex() connect()的扩展版本,出错时会返回错误码而不是抛出异常
共用套接字方法
s.recv() 接收TCP数据
s.send() 发送TCP数据
s.sendall() 完整发送TCP数据
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字
阻塞式套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间
面向文件的套接字的方法
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字关联的文件
创建TCP服务器
先给出伪代码,来理解服务器创建的过程。
s = socket() #创建服务器套接字
s.bind() #把地址绑定到套接字上
s.listen() #监听连接
inf_loop: #服务器无限循环
c=s.accept()#接受客户的连接,accept()函数会返回一个连接对象和连接地址元祖
comm_loop:#通讯循环
c.recv()/c.send()#收发数据
c.close()#关闭客户连接
s.close()#关闭服务器连接
服务器在一个端口接受请求,一旦接受到连接,accept()函数就会返回一个单独的客户的套接字对象用户后续的通信。这样,接受到一个连接后便使用其他的端口通信而不妨碍服务的监听。通常,服务器使用多线程技术来处理。使用accept()函数返回的套接字对象来创建一个线程专门处理客户连接。主端口就能空出来接受其他的客户端请求了。
下面的示例来自《Python核心编程第二版》
TCP服务器示例
TCP时间戳服务器tsTserv.py
#!/usr/bin/env python
from socket import * #为了防止名字空间重复,尽量不要这么导入模块
from time import ctime
HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket(AF_INET,SOCK_STREAM) #TCP/IP套接字
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
while True:
print 'Waiting for connection...'
tcpCliSock,addr = tcpSerSock.accept()
print 'connected from:',addr
while True:
date = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send('[%s]%s' %(ctime(),data))
tcpCliSock.close()
tcpSerSock.close()
程序就不解释了,,很明了了已经。。。
下面是客户端的伪代码
cs = socket() #创建客户端套接字
cs.connect() #连接到服务器
comm_loop: #通信循环
cs.send()/cs.recv() # 对话(发送/接收)
cs.close() # 关闭客户套接字
客户端的实现
#!/usr/bin/env python
from socket import *
HOST = 'localhost'
PORT = 21567
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()
客户端的功能很简单,获得用户输入发送到时间戳服务器,接收服务器加上时间戳的数据并显示出来
如果服务器端没有运行,执行客户端会抛出异常,同样,结束服务器端的循环也会抛出异常,为了优雅的退出,友好的错误输出,可以将必要的程序比如服务器的循环放在try-except语句的try子句当中,在异常处理子句中调用close()来关闭套接字。
关于TCP/IP套接字也就介绍这么些内容,各个流程按伪代码给出的进行操作。
UDP连接是无连接的,在处理上会与TCP套接字有所不同。具体该怎么实现,就等下一次吧。。。
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返回)才能执行,而类方法则不需要。
SocketServer 模块
SocketServer
模块是一个十分有用的模块,它可以简化socket服务器的开发。有关这个模块的使用的讨论已经远远超出了本
教程的范围,但是我将展示一下它的基本用法,然后您可以参阅参考资料一节中给出的链接。
考虑清单 2 中给出的例子。此处,我们实现了一个简单的 “Hello World” 服务器,当客户机连接它时,它就会显示这样一条消息。我首先创建一个请求处理程序,它继承了
SocketServer
.
StreamRequestHandler
类。我们定义了一个名为 handle 的方法,它处理服务器的请求。服务器所做的每件事情都必须在这个函数的上下文中进行处理(最后,关闭这个 socket)。这个过程的工作方式非常简单,但是您可以使用这个类来实现一个简单的 HTTP 服务器。在 handle 方法中,我们打一个招呼就退出了。
现在连接处理程序已经准备就绪了,剩下的工作是创建 socket 服务器。我们使用了
SocketServer
.TCPServer 类,并提供了地址和端口号(要将服务器绑定到哪个端口上)以及请求处理方法。结果是一个 TCPServer 对象。调用 serve_forever 方法启动服务器,并使其对这个连接可用。
清单 2. 用
SocketServer
模块实现一个简单的服务器
Toggle line numbers
Toggle line numbers
1 import SocketServer
2
3 class hwRequestHandler( SocketServer.StreamRequestHandler ):
4 def handle( self ):
5 self.wfile.write("Hello World!/n")
6
7
8 server = SocketServer.TCPServer( ("", 2525), hwRequestHandler )
9 server.serve_forever()
就是这样!Python 允许这种机制的任何变种,包括 UDPServers 以及派生进程和
线程的服务器。请参阅 参考资料一节中更多信息的链接。