python网络编程解疑

看论坛上好多同学对第7周网络编程不甚理解,因此有必要把我的理解贴出来和大家分享一下,希望能帮助大家更好地理解。
帖子中有什么不足之处欢迎大家指正。

python网络编程难的地方不在网络,而在事件反馈机制。
关键要理解什么时候产生事件,以及事件反馈回来结果参数及其含义。
整个过程其实就是注册事件-》产生事件-》返回事件-》处理事件 的整个流程,下面我用老师课上的select例子来描述(通过注释描述)这个过程。

  1. import socket
  2. import select
  3. import Queue

  4. #服务端监听地址和端口
  5. server=('127.0.0.1',2013)
  6. #创建socket
  7. sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

  8. #设置socket选项和监听过程
  9. sock.setblocking(False)
  10. sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
  11. sock.bind(server)
  12. sock.listen(10)

  13. #读事件的socket列表,这个很重要,不在这个列表中的socket得不到事件反馈通知,初始只有服务监听socket
  14. rlists=[sock]
  15. #读事件的socket列表
  16. wlists=[]
  17. #接收到的数据队列
  18. msg_que={}
  19. #等待超时20秒
  20. timeout=20
  21. #从后面逻辑看,while rlists相当于while True
  22. while rlists:
  23. """
  24. select过程就是等待网络事件的过程,分别是读、写和异常事件,这集中了注册事件、产生事件和返回事件的过程
  25. 注册事件: 是关注rlists(读),wlists(写),rlists(异常)中的socket列表
  26. 产生事件: 当客户端socket连接和发送、服务端向客户端socket写入、以及网络异常这些事件就会分别产生读、写和异常事件
  27. 返回事件: 当服务端接收到这些事件就返回相应的列表,分别对应rs,ws,es
  28. 如果在timeout时间内没有产生上述事件,也会返回,此时rs,ws,es均为空
  29. """
  30.     rs,ws,es = select.select(rlists,wlists,rlists,timeout)
  31. #这说明没有socket事件
  32.     if not(rs or ws or es):
  33.         print "timeout......"
  34.         continue
  35. #读事件,可能有多个socket产生读事件,s是读事件发生的socket
  36.     for s in rs:
  37. #这个很重要,s是服务监听socket,所以是连接请求事件
  38.         if s is sock:
  39. #接收socket连接,conn是负责和客户端socket进行读写操作的socket
  40.             conn,addr=s.accept()
  41.             print 'connet by ', addr
  42.             conn.setblocking(False)
  43.         #这个非常重要,如果不把conn加入rlists,那么该socket上的读写事件将得不到通知
  44.             rlists.append(conn)
  45.         #初始化conn的数据队列,后面读到数据就放入到这个队列中
  46.             msg_que[conn]=Queue.Queue()
  47. #这是socket读事件
  48.         else:
  49.         #读数据
  50.             data=s.recv(1024)
  51.            #接收到数据
  52.             if data:
  53.                 print data
  54.               #将读到的数据放入s的数据队列
  55.                 msg_que[s].put(data)
  56.               #将s加入到wlists队列,如果没有这个,s上发生的写事件就得不到事件通知
  57.                 if s not in wlists:
  58.                     wlists.append(s)
  59.            #没有接收到数据,通常是客户端主动断开socket连接,此时要将s从wlists和rlists中移除,并关闭s,清除s的数据队列
  60.             else:
  61.                 if s in wlists:
  62.                     wlists.remove(s)
  63.                 rlists.remove(s)
  64.                 s.close()
  65.                 del msg_que[s]
  66. #写事件,可能有多个socket产生写事件,s是写事件发生的socket
  67.     for s in ws:
  68.         try:
  69.         #获取数据队列中的读到的数据
  70.             msg=msg_que[s].get_nowait()
  71.         except Queue.Empty:
  72.         #数据队列中没有数据
  73.             print "msg empty"
  74.             wlists.remove(s)
  75.         else:
  76.         #发送数据
  77.             s.send(msg)

  78. #异常事件, s是发生异常的socket
  79.     for s in es:
  80.         print "except",s.getpeername()
  81.        #将s从rlists中移除
  82.         if s in rlists:
  83.             rlists.remove(s)
  84.        #将s从wlists中移除
  85.         if s in wlists:
  86.             wlists.remove(s)
  87.         s.close()
  88.         del msg_que[s]
  89.    
  90. sock.close()
  91. print 'server sock closed'
复制代码


poll、epoll流程都是类似的,理解了这个,其它的应该也不在话下
推荐一篇经典e文,我还没来得及看。
http://scotdoyle.com/python-epoll-howto.html

刚看完视频不久,以上是我的理解,希望大家拍砖!

你可能感兴趣的:(python开发)