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

[经验分享] Python网络编程基础 (Client, Server)

[复制链接]

尚未签到

发表于 2015-4-27 13:23:44 | 显示全部楼层 |阅读模式
  网络客户端:
  1. 理解socket: socket是操作系统I/O系统的延伸部分,它扩展了操作系统的基本I/O到网络通信,使进程和机器之间的通信成为可能。建立 socket 需要通过调用 socket() 函数,并且还需要另外的调用来连接和激活它们( recv() 和 send() ) 。
  2. 建立socket:首先需要建立一个实际的socket对象,其次需要把它连接到远程服务器上。建立socket对象的时候需要告诉系统两件事情:通信协议和协议家族。
  通信协议:Internet通信类型基本上都是AF_INET,和 IPv4 对应。
  协议家族:SOCK_STREAM ( TCP通信 ) 或 SOCK_DGRAM ( UDP通信 ) 。
  TCP建立socket连接:
  



s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
  

UDP建立socket连接:
  



s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
  

3. 连接socket:一般需要一个tuple,包含远程主机名( 或IP地址) 和远程端口。
  连接一个socket一般使用如下代码:
  



s.connect(( "www.example.com", 80))
  

由以上代码可看出,我们可以通过使用域名来连接远程主机,因为python为我们做了DNS解析。
  http站点的的默认端口是80。python的socket库包含一个getservbyname()的函数可以自动查询服务器端口号列表。
  该函数需要两个参数:协议名和端口名。
  



port = socket.getservbyname( "http", "tcp" )
  

注:getservbyname() 方法是直接调用操作系统API。
  4. 从socket获取信息。
  

DSC0000.gif DSC0001.gif connect.py



1 #!/usr/bin/env python
2 # Information Example
3  
4  import socket
5
6  print "Creating socket... "
7 s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
8  print "Done!"
9
10  print "Looking up port number... "
11 port = socket.getservbyname( "http", "tcp" )
12  print "Done!"
13
14  print "Connecting to remote host on port %d..." % port
15 s.connect(( "www.google.com", port ))
16  print "Done!"
17
18  print "Connected from ", s.getsockname()
19  print "Connected to ", s.getpeername()
  

运行结果:
DSC0002.jpg
  可以看到,本次连接系统分配的端口号为2728,每次运行该程序此端口号一般不相同。
  5. 利用socket通信。
  python提供了两种通信方法:socket对象和文件类对象。
  socket 对象提供了操作系统的 send(), sendto(), recv(), recvfrom() 调用的接口。
  文件类对象则提供了 read(), write() readline() 等python接口。
  文件类对象一般只对TCP连接工作得很好,对UDP连接反而不是很发。
  6. 处理错误与socket异常。
  与一般I/O和通信问题有关的 socket.error;
  与查询地址信息有关的 socket.gaierror;
  与其他地址错误有关的 socket.herror;
  与在一个socket上调用settimeout()后,处理超时有关的socket.timeout。
  7. UDP客户端和TCP客户端的区别。
  . 当socket建立的时候,程序调用的是 socket.SOCK_DGRAM ,而不是 SOCK_STREAM 。这会向操作系统提示socket将使用UDP通信,而不是TCP。
  . 对socket.getsevbyname()的调用寻找的是UDP端口,而不是TCP的。不是协议可使用同一端口号。
  . 程序没有办法探测服务器什么时候发送完数据。这是因为这里其实没有什么实际的连接。对connect()的调用只是初始化了一些内在参数。同时,服务器也许不会返回任何数据,或者数据也许在传输过程中丢失,程序并没有智能地判断这个问题,因此,当结束等待传来的信息包时,需要按下Ctrl-C 。
  
  网络服务器
  1. 服务器的特点是等待来自客户端的请求,发送应答。与客户端类似,使用的是和客户端同样的socket接口,但建立socket的细节却是不同的。
  2. 准备连接。
  . 建立socket对象。可以使用和客户端中使用的同一个socket对象。



s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
  


  . 设置socket选项(可选)。



s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
  


  . 绑定到一个端口(同样,也可以是一个指定的网卡)。bind()函数第一个参数是你要绑定的IP地址,通常为空,意思是可以绑定到所有的接口和地址。



s.bind(( host, port ))
  


  . 侦听连接。唯一参数指明了服务器实际处理连接的时候,允许有多少个未决(等待)的连接在队列中等待。



s.listen(5)
  


  3. 接受连接。
  通常服务器连续运行的办法是小心地设计一个无限循环。
  

server.py



1 #!/usr/bin/env python
2 # Base Server
3  
4  import socket
5
6 host = ''
7 port = 51423
8
9 s = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
10 s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
11 s.bind((host, port))
12  print "Waiting for connections... "
13 s.listen(1)
14
15 while 1:
16     clientsock, cliendaddr = s.accept()
17     print "Got connection from ", clientsock.getpeername()
18     cliendsock.close()
  

这里的循环是:当你调用 accept() 的时候,它只在有一个客户端连接后才返回,同时程序会停止,并不使用任何CPU资源。
  一个停止并等待输入或输出的程序称为被阻塞的程序。
  测试此服务器程序可以使用操作系统的 telnet 指令。对于这个程序,先运行服务器,接着运行 telnet localhost 51423 。服务器程序会报告一个连接,并且 telnet 程序会立即终止。
  4. 使用UDP。
  在服务器端使用UDP,可以像使用TCP一样建立一个socket, 设置选项,并调用 blind() 函数。然而,不必使用 listen() 或 accept() 函数,仅仅使用 recvfrom() 函数就可以了。这个函数实际上会返回两个信息:收到的数据,以及发送这些数据的程序地址和端口号。
  5. 避免死锁。
  死锁发生在当一个服务器和客户端同时试图往一个连接上写东西和同时从一个连接上读的时候。在这些情况下,没有进程可以得到任何数据(如果它们都正在读)。因此,如果它们正在写,向外的buffer会被充满,结果它们就好像是被骗了,什么都做不了。(解决?确保客户端每次执行完send()后进行一次recv();简单地使客户端发送较少的数据;使用多线程,使客户端可以同时发送和接收。)小心地设计协议并适当地使用超时,可以把死锁出现的频繁和影响减至最小。
  

运维网声明 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-61266-1-1.html 上篇帖子: Python服务器开发三:Socket 下篇帖子: python string和PyQt的QString的区别(转贴)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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