使用套接字进行网络编程,须要先了解一些有关网络编程的背景信息。python
同步:所谓同步,就是在c端发出一个功能调用时,在没有获得结果以前,该调用就不返回。也就是必须一件一件事作,等前一件作完了才能作下一件事。ajax
例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事编程
异步:异步的概念和同步相对。当c端一个异步过程调用发出后,调用者不能马上获得结果。实际处理这个调用的部件在完成后,经过状态、浏览器
通知和回调来通知调用者。服务器
例如 ajax请求(异步): 请求经过事件触发->服务器处理(这是浏览器仍然能够做其余事情)->处理完毕网络
阻塞:调用是指调用结果返回以前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。函数只有在获得结果以后才会返回。有人也许会把阻塞调用和同步调用等同起来,实际上他是不一样的。对于同步调用来讲,不少时候当前线程仍是激活的,只是从逻辑上当前函数没有返回而已。 例如,咱们在socket中调用recv函数,若是缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各类各样的消息。架构
非阻塞:非阻塞和阻塞的概念相对应,指在不能马上获得结果以前,该函数不会阻塞当前线程,而会马上返回。框架
用取快递来举例就是:异步
阻塞:好比到你某个时候到A楼一层(假如是内核缓冲区)取快递,可是你不知道快递何时过来,你又不能干别的事,只能死等着。但你能够睡觉(进程处于休眠状态),由于你知道快递把货送来时必定会给你打个电话(假定必定能叫醒你)。socket
非阻塞:若是用轮询的方法,每隔5分钟到A楼一层(内核缓冲区)去看快递来了没有。若是没来,当即返回。而快递来了,就放在A楼一层,等你去取。
使用到的主要模块就是socket模块。
通用TCP服务器的建立流程:
ss = socket() # 建立服务器套接字 ss.bind() # 套接字与地址绑定 ss.listen # 监听链接 inf_loop: # 服务器无限循环 cs = ss.accept() # 接收客户端链接 comm_loop: # 通讯循环 cs.recv()/cs.send() # 对话(接收/发送) cs.close() # 关闭客户端套接字 ss.close() # 关闭服务器套接字(可选)
示例:
#!/usr/bin/python from socket import * from time import ctime HOST = '' PORT = 21567 BUFSIZ = 1024 ADDR = (HOST, PORT) tcpSerSock = socket(AF_INET, SOCK_STREAM) #创建TCP链接 tcpSerSock.bind(ADDR) tcpSerSock.listen(5) while True: print 'waiting for new 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()
通用TCP客户端的建立流程:
cs = socket() # 建立客户端套接字 cs.connect() # 尝试链接服务器 comm_loop: # 通讯循环 cs.send()/cs.recv() # 对话(发送/接收) cs.close() # 关闭客户端套接字
示例:
#!/usr/bin/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()
首先启动服务端,再用客户端链接。
客户端显示的是发送的数据和服务端返回带时间戳的数据:
服务端的输出只要是诊断性的:
建立UDP链接相比于TCP简单的多,这里就不演示了。
SocketServer简化了网络服务器的编写。它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。这4个类是同步进行处理的,另外经过ForkingMixIn和ThreadingMixIn类来支持异步。
建立服务器的步骤。首先,你必须建立一个请求处理类,它是BaseRequestHandler的子类并重载其handle()方法。其次,你必须实例化一个服务器类,传入服务器的地址和请求处理程序类。最后,调用handle_request()通常是调用其余事件循环或者使用select())或serve_forever()。集成ThreadingMixIn类时须要处理异常关闭。daemon_threads指示服务器是否要等待线程终止,要是线程互相独立,必需要设置为True,默认是False。
不管用什么网络协议,服务器类有相同的外部方法和属性。该模块在python3中已经改名为socketserver。
这里不做研究和演示。
Twisted是用Python实现的基于事件驱动的网络引擎框架。Twisted诞生于2000年初,在当时的网络游戏开发者看来,不管他们使用哪一种语言,手中都鲜有可兼顾扩展性及跨平台的网络库。Twisted的做者试图在当时现有的环境下开发游戏,这一步走的很是艰难,他们迫切地须要一个可扩展性高、基于事件驱动、跨平台的网络开发框架,为此他们决定本身实现一个,并从那些以前的游戏和网络应用程序的开发者中学习,汲取他们的经验教训。
Twisted支持许多常见的传输及应用层协议,包括TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。就像Python同样,Twisted也具备“内置电池”(batteries-included)的特色。Twisted对于其支持的全部协议都带有客户端和服务器实现,同时附带有基于命令行的工具,使得配置和部署产品级的Twisted应用变得很是方便。
本文不做研究和演示。
参考书籍:Python核心编程(第三版)