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

[经验分享] Dave Python 练习十八 -- 网络编程

[复制链接]

尚未签到

发表于 2017-5-3 09:05:36 | 显示全部楼层 |阅读模式
  

  

  #encoding=utf-8###***************  网络编程  ***************#**********  Part 1: 套接字:通讯端点  *******************### 1.1 套接字#套接字起源于20 世纪70 年代加利福尼亚大学伯克利分校版本的Unix,即人们所说的BSD Unix。#因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同#一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或IPC。套接字有两种,分别是基于文#件型的和基于网络型的。#Unix 套接字是我们要介绍的第一个套接字家族。其“家族名”为AF_UNIX(在POSIX1.g 标准中#也叫AF_LOCAL),表示“地址家族:UNIX”。包括Python 在内的大多数流行平台上都使用术语“地址#家族”及其缩写“AF”。而老一点的系统中,地址家族被称为“域”或“协议家族”,并使用缩写“PF”#而不是“AF”。同样的,AF_LOCAL(在2000-2001 年被列为标准)将会代替AF_UNIX。不过,为了向后#兼容,很多系统上,两者是等价的。Python 自己则仍然使用AF_UNIX。#另一种套接字是基于网络的,它有自己的家族名字:AF_INET,或叫“地址家族:Internet”。#还有一种地址家族AF_INET6 被用于网际协议第6 版(IPv6)寻址上。还有一些其它的地址家族,所有地址家族中,AF_INET 是使用最广泛的一个。##Python 2.5 中加入了一种Linux 套接字的支持:AF_NETLINK套接字家族让用户代码与内核代码之间的IPC 可以使用标准BSD 套#接字接口。而且,相对之前那些往操作系统中加入新的系统调用,proc 文件系统支持或是“IOCTL”等笨重的方案来说,这种方法显得更为优美,更为安全。##Python 只支持AF_UNIX,AF_NETLINK,和AF_INET 家族。## 1.2 套接字地址:主机与端口#如果把套接字比做电话的插口——即通讯的最底层结构,那主机与端口就像区号与电话号码的#一对组合。有了能打电话的硬件还不够,你还要知道你要打给谁,往哪打。一个Internet 地址由网#络通讯所必需的主机与端口组成。而且不用说,另一端一定要有人在听才可以。否则,你就会听到#熟悉的声音“对不起,您拨的是空号,请查对后再播”。你在上网的时候,可能也见过类似的情况,#如“不能连接该服务器。服务器无响应或不可达”。#合法的端口号范围为0 到65535。其中,小于1024 的端口号为系统保留端口。如果你所使用的#是Unix 操作系统,保留的端口号(及其对应的服务/协议和套接字类型)可以通过/etc/services#文件获得。## 1.3 面向连接与无连接##1.3.1 面向连接#无论你使用哪一种地址家族。套接字的类型只有两种。一种是面向连接的套接字,即在通讯之#前一定要建立一条连接,就像跟朋友打电话时那样。这种通讯方式也被称为“虚电路”或“流套接#字”。面向连接的通讯方式提供了顺序的,可靠的,不会重复的数据传输,而且也不会被加上数据边#界。这也意味着,每一个要发送的信息,可能会被拆分成多份,每一份都会不多不少地正确到达目#的地。然后被重新按顺序拼装起来,传给正在等待的应用程序。#实现这种连接的主要协议就是传输控制协议(即TCP)。要创建TCP 套接字就得在创建的时候,#指定套接字类型为SOCK_STREAM。TCP 套接字采用SOCK_STREAM 这个名字,表达了它做为流套接字的#特点。由于这些套接字使用Internet 协议(IP)来查找网络中的主机,这样形成的整个系统,一般#会由这两个协议(TCP 和IP)来提及,即TCP/IP。## 1.3.2 无连接#与虚电路完全相反的是数据报型的无连接套接字。这意味着,无需建立连接就可以进行通讯。#但这时,数据到达的顺序,可靠性及数据不重复性就无法保证了。数据报会保留数据边界,这就表#示,数据不会像面向连接的协议那样被拆分成小块。#使用数据报来传输数据就像邮政服务一样。邮件和包裹不一定会按它们发送的顺序到达。事实#上,它们还有可能根本到不了!而且,由于网络的复杂性,数据还可能被重复传送。#既然数据报有这么多缺点,为什么还要使用它呢?由于#面向连接套接字要提供一些保证,以及要维持虚电路连接,这都是很重的额外负担。数据报没有这#些负担,所以它更“便宜”。通常能提供更好的性能,更适合某些应用场合。#实现这种连接的主要协议就是用户数据报协议(即UDP)。要创建UDP 套接字就得在创建的时候,#指定套接字类型为SOCK_DGRAM。SOCK_DGRAM 这个名字,也许你已经猜到了,来自于单词“datagram”#(“数据报”)。由于这些套接字使用Internet 协议来查找网络中的主机,这样形成的整个系统,一#般会由这两个协议(UDP 和IP)来提及,即UDP/IP。#**********  Part 2: Python 中的网络编程  *******************## 2.1 socket()模块函数#要使用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 的套接字,你要这样调用socket.socket():#tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)##同样地,创建一个UDP/IP 的套接字,你要这样:#udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)##由于socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用#'from socket import *',我们就把socket 模块里的所有属性都带到我们的命名空间里了,这样能#大幅减短我们的代码。#tcpSock = socket(AF_INET, SOCK_STREAM)#当我们创建了套接字对象后,所有的交互都将通过对该套接字对象的方法调用进行。##2.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()               关闭套接字####Blocking-Oriented Socket Methods#s.setblocking()         设置套接字的阻塞与非阻塞模式#s.settimeout()          设置阻塞套接字操作的超时时间#s.gettimeout()          得到阻塞套接字操作的超时时间#####面向文件的套接字的函数#s.fileno()              套接字的文件描述符#s.makefile()            创建一个与该套接字关连的文件#2.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 是一个面向连接的通讯系统,在TCP 服务器#可以开始工作之前,要先完成一些设置。TCP 服务器必需要“监听”(进来的)连接,设置完成之后,#服务器就可以进入无限循环了。##一个简单的(单线程的)服务器会调用accept()函数等待连接的到来。默认情况下,accept()#函数是阻塞式的,即程序在连接到来之前会处于挂起状态。套接字也支持非阻塞模式。##一旦接收到一个连接,accept()函数就会返回一个单独的客户的套接字用于后续的通讯。#在临时套接字创建好之后,通讯就可以开始了。客户与服务器都使用这个新创建的套接字进行#数据的发送与接收,直到通讯的某一方关闭了连接或发送了一个空字符串之后,通讯就结束了。#在代码中,当客户连接关闭后,服务器继续等待下一个客户的连接。代码的最后一行,会把服#务器的套接字关闭。由于服务器处在无限循环中,不可能会走到这一步,所以,这一步是可选的。#我们写这一句话的主要目的是要提醒读者,在设计一个更智能的退出方案的时候,比方说,服务器#被通知要关闭的时,要确保close()函数会被调用。#示例:tsTserv.py 创建一个TCP 服务器程序,当客户端连接上来之后返回'hello dave'#encoding=utf-8#from socket import *#from time import ctime##HOST = ''   #HOST 变量为空,表示bind()函数可以绑定在所有有效的地址上。#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(b'Hello Dave') #注意在Python 3.x 版本这里只能send bytes类型##tcpCliSock.close()#tcpSerSock.close()## 2.4 创建TCP 客户端#伪代码:#cs = socket() # 创建客户套接字#cs.connect() # 尝试连接服务器#comm_loop: # 通讯循环#cs.send()/cs.recv() # 对话(发送/接收)#cs.close() # 关闭客户套接字#所有的套接字都由socket.socket()函数创建。在客户有了套接字之后,马上就可#以调用connect()函数去连接服务器。连接建立后,就可以与服务器开始对话了。在对话结束后,客户就可以关闭套接字,结束连接。#tcTlnt.py 的代码。程序连接到服务器,向服务器发送‘hello world’,服务器返回‘hello dave’#from socket import *##HOST = 'localhost'  #服务器的主机名与端口号#PORT = 21567    #端口号要与服务器上的设置完全相同#BUFSIZ = 1024#ADDR = (HOST, PORT)##tcpCliSock = socket(AF_INET, SOCK_STREAM)#tcpCliSock.connect(ADDR)##while True:#    tcpCliSock.send(b'Hello world')#    data = tcpCliSock.recv(BUFSIZ)#    #    if not data:#        break#    print(data)##tcpCliSock.close()## 2.6 创建一个UDP 服务器#由于UDP 服务器不是面向连接的,所以不用像TCP 服务器那样做那么多设置工作。事实上,并不用设置什么东西,直接等待进来的连接就好了。#ss = socket() # 创建一个服务器套接字#ss.bind() # 绑定服务器套接字#inf_loop: # 服务器无限循环#cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送)#ss.close() # 关闭服务器套接字##从伪代码中可以看出,使用的还是那套先创建套接字然后绑定到本地地址(主机/端口对)的方法。#无限循环中包含了从客户那接收消息,返回加了时间戳的结果和回去等下一个消息这三步。#同样的,由于代码不会跳出无限循环,所以,close()函数调用是可选的。我们写这一句话的原因是#要提醒读者,在设计一个更智能的退出方案的时候,要确保close()函数会被调用。##UDP 时间戳服务器 (tsUserv.py)#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(ctime().encode('utf-8'), addr)  #这里注意在Python 3里sendto 需要用bytes 进行传送,所以需要使用encode进行转换#    print('...received from and returned to:', addr)##udpSerSock.close()## 2.7 创建一个UDP 客户端#伪代码如下:#cs = socket() # 创建客户套接字#comm_loop: # 通讯循环#cs.sendto()/cs.recvfrom() # 对话(发送/接收)#cs.close() # 关闭客户套接字## UDP 客户端,程序会提示用户输入要传给服务器的信息,显示服务器返回的加了时间戳的结果。#from socket import *##HOST = 'localhost'#PORT = 21567#BUFSIZ = 1024#ADDR = (HOST, PORT)##udpCliSock = socket(AF_INET, SOCK_DGRAM)##while True:#    data = input('> ')#    if not data:#        break#    udpCliSock.sendto(data.encode('utf-8'), ADDR)  #这里注意在Python 3里sendto 需要用bytes 进行传送,所以需要使用encode进行转换#    data, ADDR = udpCliSock.recvfrom(BUFSIZ)#    if not data:#        break#    print(data)##udpCliSock.close()#先运行服务器,在运行客户端,提示输入data,然后服务器返回时间。## 2.8 套接字模块属性#socket 模块属性##属性名字                            描述#####数据属性#AF_UNIX, AF_INET, AF_INET6          Python 支持的套接字家族#SO_STREAM, SO_DGRAM                 套接字类型 (TCP = 流, UDP = 数据报)#has_ipv6                            表示是否支持IPv6 的标志变量#####异常#error                   套接字相关错误#herrora                 主机和地址相关的错误#gaierror                地址相关的错误#timeout                 超时#####函数#socket()                用指定的地址家族,套接字类型和协议类型(可选)创建一个套接字对象#socketpair()            用指定的地址家族,套接字类型和协议类型(可选)创建一对套接字对象#fromfd()                用一个已经打开的文件描述符创建一个套接字对象#####数据属性#ssl()                    在套接字初始化一个安全套接字层(SSL)。不做证书验证。#getaddrinfo()            得到地址信息#getfqdn()                返回完整的域的名字#gethostname()           得到当前主机名#gethostbyname()         由主机名得到对应的ip 地址#gethostbyname_ex()      gethostbyname()的扩展版本,返回主机名,主机所有的别名和IP 地址列表。#gethostbyaddr()         由IP 地址得到DNS 信息,返回一个类似gethostbyname_ex()的3 元组。#getprotobyname()        由协议名(如'tcp')得到对应的号码。#getservbyname()/        由服务名得到对应的端口号或相反#getservbyport()         两个函数中,协议名都是可选的。#ntohl()/ntohs()         把一个整数由网络字节序转为主机字节序#htonl()/htons()         把一个整数由主机字节序转为网络字节序#inet_aton()/            把IP 地址转为32 位整型,以及反向函数。(仅对IPv4 地址有效)#inet_ntoa()#inet_pton()/            把IP 地址转为二进制格式以及反向函数。(仅对IPv4 地址有效)#inet_ntop()#getdefaulttimeout()/    得到/设置默认的套接字超时时间,单位秒(浮点数)#setdefaulttimeout()


  

  -------------------------------------------------------------------------------------------------------
Blog: http://blog.csdn.net/tianlesoftware
Weibo: http://weibo.com/tianlesoftware
Email: dvd.dba@gmail.com
DBA1 群:62697716(满);  DBA2 群:62697977(满)  DBA3 群:62697850(满)
DBA 超级群:63306533(满); DBA4 群: 83829929(满) DBA5群: 142216823(满)
DBA6 群:158654907(满)  DBA7 群:69087192(满)  DBA8 群:172855474
DBA 超级群2:151508914 DBA9群:102954821   聊天 群:40132017(满)
--加群需要在备注说明Oracle表空间和数据文件的关系,否则拒绝申请

运维网声明 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-372340-1-1.html 上篇帖子: python访问需要登录的网页 下篇帖子: Dave Python 练习七 -- 元组
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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