设为首页 收藏本站
查看: 1152|回复: 0

[经验分享] [PYTHON] 核心编程笔记(16.Python网络编程)

[复制链接]

尚未签到

发表于 2018-8-8 10:12:48 | 显示全部楼层 |阅读模式
  16.1 介绍
  16.1.1 什么是客户/服务器架构?
  硬件的客户/服务器架构
  软件客户/服务器架构
  16.1.2 客户/服务器网络编程
  16.2 套接字: 通讯端点
  16.2.1 什么是套接字?
  套接字是一种具有通讯端点感念的计算机网络数据结构
  16.2.2 套接字地址:主机与端口
  主机和端口类似区号和电话号码的一对组合
  合法的端口号范围是0到65535,小于1024的端口号为系统保留端口
  16.2.3 面向连接与无连接
  面向连接(TCP)
  套接字只有两种一种是面向连接套接字,即在通讯之前一定要建立一条连接,这种通讯方式提供了顺序的,可靠的不会重复的数据传输,每一份要发送的信息都会拆分成多份,每份都会不多不少的到达目的地后重新按顺序拼装起来,传给正在等待的应用程序
  实现这种连接的主要协议就是传输控制协议(即TCP)
  要创建TCP套接字就得在创建的时候指定套接字类型为SOCK_STREAM,表示为流套接字
  无连接(UDP)
  与虚电路相反的数据报型是无连接套接字,即无需建立连接就可以进行通讯,这意味着数据到达的顺序,可靠性及数据不重复性就无法保证,数据会保留在数据边界,数据不会像TCP协议那样被拆封为小块
  使用数据报来传输数据就像邮政服务,邮件包裹不一定会按照他们发送的顺序到达,而且可能还到达不了,而且还可能被重传
  由于面向连接套接字提供一些维持虚电路连接的开销,数据报较他来说基本上没有负担,所以它能更好的提供性能,适合于某些应用场合
  实现这种连接的主要协议就是用户数据报协议(即UDP)
  要创建UDP套接字就得在创建的时候指定套接字类型为SOCK_DGRAM,即datagram数据报
  由于这些套接字使用Internet协议来查找网络中的主机,这样形成的整个系统一般都会由这两对协议(TCP/IP)和(UDP/IP)来提及
  16.3 Python中的网络编程
  本节我们主要使用socket模块,模块中的socket()函数被用来创建套接字,其有自己的一套函数来提供基于套接字的网络传输
  16.3.1 socket()模块函数:
  创建套接字语法:
  socket(socket_family,socket_type,protocol=0)
  socket_family可以是AF_UNIX或AF_INET,soket_type可以是SOCK_STREAM或SOCK_DGRAM,protocal一般不填,默认为0
  创建一个TCP/IP套接字,需要调用socket.socket()
  tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  创建一个UDP/IP套接字,需要调用socket.socket()
  udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  使用from socket import * 将socket模块里的所有属性带到命名空间里
  当我们创建了套接字对象后,所有的交互豆浆通过对该套接字对象的方法进行调用
  16.3.2 套接字对象(内建)方法
  函数描述
  s.bind()绑定地址(主机,端口号对)到套接字
  s.listen()开始TCP监听
  s.accept()被动接受TCP服务器连接,(阻塞式)等待连接到来
  s.connect()主动初始化TCP服务器连接
  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()创建一个与该套接字关联的文件
  16.3.3 创建一个TCP服务器
  ss.socket()#创建服务器套接字
  ss.bind()#把地址绑定到套接字上
  ss.listen()#监听连接
  inf_loop()#服务器无限循环
  cs=ss.accept()#接受客户的连接
  comm_loop()#通讯循环
  cs.recv()/cs.send()#对话(接收与发送)
  cs.close()#关闭客户套接字
  ss.close()#关闭服务器套接字(可选)
  所有套接字都用socket().socket()函数创建,服务器需要"坐在某个端口上"等待请求,所以需要绑定到一个本地地址上,TCP服务器负责监听连接,设置完,服务器就可以进行无限循环了
  默认服务器会调用accept()阻塞式函数等待连接,来之前程序一直会处于挂起状态
  一旦接收到一个连接,accept()函数就会返回一个单独的客户的套接字用于后续通讯.
  例,tsTserv.py文件会创建一个TCP服务程序,这个程序会把客户发过来的字符串加上一个时间戳(格式:'[时间]数据')返回给客户
  # vi tsTserv.py
  --------------------------------
  #!/usr/bin/env python
  #coding: UTF-8
  from socket import *
  from time import ctime
  HOST = ''               #绑定IP
  PORT = 21567            #端口号
  BUFSIZ = 1024           #缓冲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))
  print [ctime()],':',data
  tcpCliSock.close()
  tcpSerSock.close()
  --------------------------------
  16.3.4 创建TCP客户端
  cs = socket()#创建客户套接字
  cs.connect()#尝试连接服务器
  comm_loop#通讯循环
  cs.send()/cs.recv()#对话(发送/接收)
  cs.close()#关闭客户套接字
  所有套接字都由socket.socket()函数创建,在客户有了套接字之后,可以调用connect()函数去连接服务器,连接服务器后,就可以与服务器对话,对话结束可关闭套接字结束连接
  例,程序连接到服务器,提示用户输入要传输的数据,然后显示服务器返回的加了时间戳的结果
  # vi tsTclnt.py
  -------------------------------
  #!/usr/bin/env python
  from socket import *
  HOST = '192.168.8.18'
  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()
  -------------------------------
  16.3.5 运行我们的客户端与服务器程序
  # python tsTserv.py
  -----------------------------
  waiting for connection...
  -----------------------------
  # python tsTclnt.py
  ----------------------------------
  >send test data
  [Thu Dec 19 12:46:36 2013] send test data
  >hi
  [Thu Dec 19 12:46:51 2013] hi
  >how are you?
  [Thu Dec 19 12:47:08 2013] how are you?
  -----------------------------------
  # python tsTserv.py
  --------------------------------------
  waiting for connection...
  ...connected from:  ('192.168.8.19', 56868)
  ['Thu Dec 19 12:46:36 2013'] : send test data
  ['Thu Dec 19 12:46:51 2013'] : hi
  ['Thu Dec 19 12:47:08 2013'] : how are you?
  ---------------------------------------
  核心提示:
  "友好地"退出的一个方法就是把服务器无限循环放在一个try-except语句中try子句中,并捕获EOFError和KeyboardInterrupt异常,在异常处理子句中,调用close()函数关闭服务器的套接字
  例:
  # vi tsTserv.py
  --------------------------------
  root@ubuntu:~/python# vi tsTserv.py
  #!/usr/bin/env python
  #coding: UTF-8
  from socket import *
  from time import ctime
  HOST = ''               #绑定IP
  PORT = 21567            #端口号
  BUFSIZ = 1024           #缓冲1K
  ADDR = (HOST,PORT)
  tcpSerSock = socket(AF_INET, SOCK_STREAM)
  tcpSerSock.bind(ADDR)   #套接字
  tcpSerSock.listen(5)    #最大连接数
  try:
  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))
  print [ctime()],':',data
  except EOFError,KeyboardInterrupt:
  tcpCliSock.close()
  tcpSerSock.close()
  --------------------------------
  # vi tsTclnt.py
  -------------------------------
  #!/usr/bin/env python
  from socket import *
  HOST = '192.168.8.18'
  PORT = 21567
  BUFSIZ = 1024
  ADDR = (HOST, PORT)
  tcpCliSock = socket(AF_INET, SOCK_STREAM)
  tcpCliSock.connect(ADDR)
  try:
  while True:
  data = raw_input('>')
  if not data:
  break
  tcpCliSock.send(data)
  data = tcpCliSock.recv(BUFSIZ)
  if not data:
  break
  print data
  except EOFError,KeyboardInterrupt:
  tcpCliSock.close()
  -------------------------------
  16.3.6 创建一个UDP服务器
  ss = socket()#创建一个服务器套接字
  ss.bind()#绑定服务器套接字
  inf_loop:#服务器无限循环
  cs = ss.recvfrom()/ss.sendto()#对话(接收与发送)
  ss.close()#关闭服务器套接字
  例,创建一个能接收客户的消息,在消息前加一个时间戳后返回的UDP服务器
  # vi tsUserv.py
  -----------------------------
  #!/usr/bin/env python
  from socket import *
  from time import ctime
  HOST = ''
  PORT = 21567
  BUFSIZ = 1024
  ADDR = (HOST,PORT)
  udpSerSock = socket(AF_INET, SOCK_DGRAM)
  udpSerSock.bind(ADDR)
  while True:
  print 'waiting for message...'
  data, addr = udpSerSock.recvfrom(BUFSIZ)
  udpSerSock.sendto('[%s] [%s]' %(ctime(), data),addr)
  print '...received from and returned to:', addr
  udpSerSock.close()
  -----------------------------
  UDP和TCP服务器的另一个重要区别是,由于数据报套接字是无连接的,所以无法把客户的链接将诶另外的套接字进行后续通讯,这些服务器只是接受消息,需要的话,给客户返回一个结果就可以了
  16.3.7 创建一个UDP客户端
  cs = socket()#创建客户套接字
  comm_loop:#通讯循环
  cs.sendto()/cs.recvfrom()#对话(发送/接收)
  cs.close()#关闭客户套接字
  在套接字对象创建好之后,我们就进入一个与服务器的对话循环,在通讯结束后,套接字就被关闭了
  例,创建一个UDP客户端,程序会提示用户输入要传给服务器的信息,显示服务器返回的加了时间戳的结果
  # vi tsUclnt.py
  -------------------------------------
  #!/usr/bin/env python
  from socket import *
  from time import ctime
  HOST = ''
  PORT = 21568
  BUFSIZ = 1024
  ADDR = (HOST,PORT)
  udpSerSock = socket(AF_INET, SOCK_DGRAM)
  udpSerSock.bind(ADDR)
  while True:
  print 'waiting for message...'
  data, addr = udpSerSock.recvfrom(BUFSIZ)
  udpSerSock.sendto('[%s] %s' %(ctime(), data),addr)
  print '...received from and returned to:', addr
  print data
  udpSerSock.close()
  -------------------------------------
  # vi tsUclnt.py
  -----------------------------------------
  #!/usr/bin/env python
  from socket import *
  HOST = '192.168.8.18'
  PORT = 21568
  BUFSIZ = 1024
  ADDR = (HOST, PORT)
  udpCliSock = socket(AF_INET,SOCK_DGRAM)
  while True:
  data = raw_input('> ')
  if not data:
  break
  udpCliSock.sendto(data, ADDR)
  data, ADDR = udpCliSock.recvfrom(BUFSIZ)
  if not data:
  break
  print data
  udpCliSock.close()
  -----------------------------------------
  16.3.8 执行UDP服务器和客户端
  # python tsUserv.py
  ---------------------------------
  waiting for message...
  ----------------------------------
  # python tsUclnt.py
  ---------------------------------
  > hi
  [Thu Dec 19 17:25:01 2013] hi
  > test1
  [Thu Dec 19 17:25:03 2013] test1
  > test2
  [Thu Dec 19 17:25:05 2013] test2
  ----------------------------------
  # python tsUserv.py
  ----------------------------------
  waiting for message...
  ...received from and returned to: ('192.168.8.19', 46359)
  hi
  waiting for message...
  ...received from and returned to: ('192.168.8.19', 46359)
  test1
  waiting for message...
  ...received from and returned to: ('192.168.8.19', 46359)
  test2
  waiting for message...
  -----------------------------------
  16.3.9 套接字模块属性
  属性名字描述
  AF_UNIX,AF_INET,AF_INET6Python支持的套接字家族
  SO_STREAM,SO_DGRAM套接字类型(TCP=流,UDP=数据报)
  has_ipv6标识是否支持IPV6的标志变量
  异常
  error套接字相关错误
  herror主机和地址相关的错误
  gaierror地址相关错误
  timeout超时
  函数
  socket()用指定的地址家族,套接字类型和协议类型(可选)创建一个套接字对象
  socketpair()用指定的地址家族,套接字类型和协议类型(可选)创建一个套接字对象
  fromfd()用一个已经打开的额文件描述符创建一个套接字对象
  数据属性
  ssl()在套接字初始化一个安全套接字层(SSL),不做整数验证
  getaddrinfo()得到地址信息
  getfqdn()返回完整的域的名字
  gethostname()得到当前主机名
  gethostbyname()由主机名得到对应的ip地址
  gethostbyname()_ex()gethostbyname()扩展版本,返回主机名,主机所有的别名和IP地址列表
  gethostbyaddr()由IP地址得到DNS信息,返回一个类似gethostbyname()_ex()的三元组
  getprotobyname()由协议名(如"tcp")得到对应的号码
  getservbyname()/由服务名得到对应的端口号或相反
  getservbyport()两个函数中,协议名都是可选的
  ntohl()/htohs()把一个整数由网络字节序转为主机字节序
  htonl()/htons()把一个整数由主机字节序转为网络字节序
  inet_aton()/把IP地址转为32位整形,以及反向函数(仅对IPV4有效)
  inet_ptoa()
  inet_pton()/把IP地址转为二进制格式以及反响函数(仅对IPV4有效)
  inet_ntop()
  getdefaulttimeout()/得到/设置默认的套接字超时时间,单位秒(浮点数)
  setdefaulttimeout()
  16.4 SocketServer模块
  SocketServer是标准库中一个高级别的模块,用于简化网络客户与服务器的实现,模块中,已经实现了一些可供使用的类
  SocketServer模块的类
  类描述
  BaseServer包含服务器的核心功能与混合(mix-in)类的钩子功能,这个类用于派生,不要直接生成
  这个类的类对象,可以考虑使用TCPServer和IDPServer
  TCPServer/基本的网络同步TCP/UDP服务器
  UDPServer
  UnixStreamServer/基本的基于文件同步TCP/UDP服务器
  UnixDatagramServer
  ForkingMixIn/实现了核心的进程化或线程化的功能,用于与服务器类进行混合(mix-in),以提供一些异步特性.
  ThreadingMixIn不要直接生成这个类的对象
  ForkingTCPServer/ForkingMixIn和TCPServer/UDPServer的组合
  ForkingUDPServer
  ThreadingTCPServer/ThreadingMixIn和TCPServer/UDPServer组合
  ThreadingUDPServer
  BaseRequestHandler包含处理服务请求的核心功能,只用于派生新的类,不要直接生成这个类的对象
  可以考虑使用StreamRequestHandler或DatagramRequestHandler
  StreamRequestHandler/TCP/UDP服务器的请求处理类的一个实现
  DatagramRequestHandler
  16.4.1 创建一个SocketServerTCP服务器
  使用SocketServer里的TCPServer和StreamRequestHandler类创建一个时间戳TCP服务器
  # vi tsTservSS.py
  ---------------------------------------------
  #!/usr/bin/env python
  from SocketServer import (TCPServer as TCP,StreamRequestHandler as SRH)
  from time import ctime
  HOST = ''
  PORT = 21567
  ADDR = (HOST, PORT)
  class MyRequestHandler(SRH):
  def handle(self):
  print "...connected from: ", self.client_address
  self.wfile.write('[%s] %s'% (ctime(), self.rfile.readline()))
  tcpServ = TCP(ADDR, MyRequestHandler)
  print 'waiting for connection...'
  tcpServ.serve_forever()
  ---------------------------------------------
  16.4.2 创建SocketServerTCP客户端
  例,这是一个时间戳TCP客户端,它知道如何与SocketServer里StreamRequestHandler对象进行
  # vi tsTclntSS.py
  ------------------------------------
  #!/usr/bin/env python
  from socket import *
  HOST = 'localhost'
  PORT = 21567
  BUFSIZ = 1024
  ADDR = (HOST, PORT)
  while True:
  tcpCliSock = socket(AF_INET, SOCK_STREAM)
  tcpCliSock.connect(ADDR)
  data = raw_input('> ')
  if not data:
  break
  tcpCliSock.send('%s\r\n' % data)
  data = tcpCliSock.recv(BUFSIZ)
  if not data:
  break
  print data.strip()
  tcpCliSock.close()
  ------------------------------------
  16.4.2 执行TCP服务器和客户端
  # python tsTservSS.py
  ---------------------------------------
  waiting for connection...
  ...connected from:  ('127.0.0.1', 40712)
  ...connected from:  ('127.0.0.1', 40713)
  ...connected from:  ('127.0.0.1', 40714)
  ...connected from:  ('127.0.0.1', 40715)
  ...connected from:  ('127.0.0.1', 40716)
  ...connected from:  ('127.0.0.1', 40717)
  ----------------------------------------
  # python tsTclntSS.py
  ---------------------------------------
  > test1
  [Fri Dec 20 04:44:02 2013] test1
  > test2
  [Fri Dec 20 04:44:16 2013] test2
  > test3
  [Fri Dec 20 04:44:18 2013] test3
  ----------------------------------------
  注:连接服务器连接了2次
  16.5 Twisted框架介绍
  Twisted是一个完全事件驱动的网络框架,它允许你使用和开发完全异步的网络应用程序和协议
  16.5.1 创建一个Twisted Reactor TCP服务器
  例,这是一个使用Twisted Internet类的时间戳TCP服务器
  # vi tsTservTW.py
  ----------------------------------
  #!/usr/bin/env python
  from twisted.internet import protocol, reactor
  from time import ctime
  PORT = 21567
  class TSServProtocol(protocol.Protocol):
  def connectionMade(self):
  clnt = self.clnt = self.transport.getPeer().host
  print '...connected from: ',clnt
  def dataReceived(self,data):
  self.transport.write('[%s] %s' %(ctime(), data))
  factory = protocol.Factory()
  factory.protocol = TSServProtocol
  print 'waiting for connection...'
  reactor.listenTCP(PORT, factory)
  reactor.run()
  ----------------------------------
  16.5.2 创建一个Twisted Reactor TCP客户端
  # vi tsTclntTW.py
  --------------------------------
  #!/usr/bin/env python
  from twisted.internet import protocol, reactor
  HOST = 'localhost'
  PORT = 21567
  class TSClntProtocol(protocol.Protocol):
  def sendData(self):
  data = raw_input("> ")
  if data:
  print '...sending %s...' % data
  self.transport.write(data)
  else:
  self.transport.loseConnection()
  def connectionMade(self):
  self.sendData()
  def dataReceived(self, data):
  print data
  self.sendData()
  class TSClntFactory(protocol.ClientFactory):
  protocol = TSClntProtocol
  clientConnectionLost = clientConnectionFailed = \
  lambda self, connector, reason: reactor.stop()
  reactor.connectTCP(HOST, PORT, TSClntFactory())
  reactor.run()
  --------------------------------
  16.5.3 执行TCP服务器和客户端
  Twisted客户显示的内容与我们之前的客户类似:
  # python tsTservTW.py
  ---------------------------
  waiting for connection...
  ----------------------------
  # python tsTclntTW.py
  -----------------------------------
  > test1
  ...sending test1...
  [Fri Dec 20 10:36:10 2013] test1
  > test2
  ...sending test2...
  [Fri Dec 20 10:36:15 2013] test2
  ------------------------------------
  # python tsTservTW.py
  ----------------------------------
  waiting for connection...
  ...connected from:  127.0.0.1
  -----------------------------------
  注: "connection from" 输出没有其他的信息,因为我们只询问服务器的transport对象的getPeer()函数要了主机地址的信息
  16.6 相关模块
  网络/套接字编程相关模块
  模块描述
  socket底层网络接口,本章讨论过
  anycore/为能异步处理客户请求的网络应用程序提供底层功能
  select在单线程网络服务器程序中,管理多个套接字连接
  SocketServer包含了些网络应用程序服务器所需要的高级别模块,提供了完整的进程和线程版本

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-548529-1-1.html 上篇帖子: Python学习笔记二(Python程序输入/输出) 下篇帖子: python常用正则表达式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表