1、套接字
1.1 socket模块
套接字是网络编程中的一个基本组件,一般包括服务器端套接字和客户端套接字。

创建服务器端过程如下:

  1. import socket
  2.  
  3. s = socket.socket()
  4.  
  5. host = socket.gethostname()
  6. port = 1234
  7. try:
  8. s.bind((host, port))
  9. except Exception, e:
  10. print e
  11. s.close()
  12.  
  13. s.listen(5)
  14. while True:
  15. c, addr = s.accept()
  16. print 'Got connection from', addr
  17. c.send('Thank you for connecting')
  18. c.close()

创建客户端过程如下:

  1. import socket, time
  2.  
  3. s = socket.socket()
  4.  
  5. host = socket.gethostname()
  6. port = 1234
  7.  
  8. s.connect((host, port))
  9. print s.recv(1024)
  10. while True:
  11. command = 'hello\n'
  12. s.send(command)
  13. time.sleep(1)

该过程的通讯方式是一问一答的形式,所以又称为阻塞或者同步网络编程。
1.2 SocketServer和它的朋友们
  SocketServer模块是标准库中很多服务器框架的基础,这些服务器框架包括BaseHTTPServer、SimpleHTTPServer、CGIHTTPServer、SimpleXMLRPCServer和DocXMLRPCServer,所有的这些服务器框架都为基础服务器增加了特定的功能。
  SocketServer包含4个基本的类:针对TCP套接字流的TCPServer;针对UDP数据报套接字的UDPServer;以及针对性不强的UnixStreamServer和UnixDatagramServer。
  在使用SocketServer服务器框架时,每当服务器收到一个请求,就会实例化一个请求处理程序,并且它的各种处理方法(handler methods)会在处理请求时被调用。基本的BaseRequestHandler类把所有的操作都放到了处理器的一个叫做handle的方法中,这个方法会被服务器调用。然后在这个方法内就可以访问属性self.request中的客户端套接字。如果使用的是流(TCPServer),那么可以使用StreamRequestHandler类,创建它的两个属性,self.rfile(用于读取)和self.wfile(用于写入)。

  1. from SocketServer import TCPServer, StreamRequestHandler
  2.  
  3. class Handler(StreamRequestHandler):
  4.  
  5. def handle(self):
  6. addr = self.request.getpeername()
  7.  
  8. print 'Got connection from', addr
  9. self.wfile.write('Thank you for connecting')
  10. server = TCPServer(('', 1234), Handler)
  11. server.serve_forever()

2、多连接
  同时可以有多个客户机连接服务端进行请求处理。有3个主要的方法能实现这个目的:分叉(forking)、线程(threading)以及异步I/O(asynchronous I/O)。它们有各自的缺点:分叉占资源,如果有太多的客户端时,分叉不能很好地分叉;线程处理能导致同步问题。
  什么是分叉:当分叉一个进程(一个运行的程序)时,基本上是复制了它,并且分叉后的两个进程都从当前的执行点继续运行,并且每个进程都有自己的内存副本(比如变量)。一个进程(原来的那个)成为父进程,另一个(复制的)成为子进程。因为分叉的进程是并行运行的,客户端之间不必相互等待。但分叉有点消耗资源(每个分叉出来的进程都需要自己的内存),这就存在了另一个选择:线程。
  什么是线程:线程是轻量级的进程或子进程,所有的线程都存在于相同的(真正的)进程中,共享内存。资源消耗的下降伴随着一个缺陷:因为线程共享内存,所以必须确保它们的变量不会冲突,或者是在同一时间修改同一内容,这就会造成混乱。
使用SocketServer框架创建分叉或者线程服务器太简单了,几乎不需要解释。注意,Windows不支持分叉。
使用分叉技术的服务器:

  1. from SocketServer import TCPServer, ForkingMixIn, StreamRequestHandler
  2.  
  3. class Server(ForkingMixIn, TCPServer): pass
  4.  
  5. class Handler(StreamRequestHandler):
  6.  
  7. def handle(self):
  8. addr = self.request.getpeername()
  9. print 'Got connection from', addr
  10. self.wfile.write('Thank you for connecting')
  11.  
  12. server = Server(('', 1234), Handler)
  13. server.serve_forever()

使用线程处理的服务器:

  1. from SocketServer import TCPServer, ThreadingMixIn, StreamRequestHandler
  2.  
  3. class Server(ThreadingMixIn, TCPServer): pass
  4.  
  5. class Handler(StreamRequestHandler):
  6.  
  7. def handle(self):
  8. addr = self.request.getpeername()
  9. print 'Got connection from', addr
  10. self.wfile.write('Thank you for connecting')
  11.  
  12. server = Server(('', 1234), Handler)
  13. server.serve_forever()

  什么是异步I/O:当一个服务器与一个客户端通信时,来自客户端的数据可能是不连续的。如果使用分叉或线程处理,那就不是问题。当一个程序在等待数据,另一个并行的程序可以继续处理它们自己的客户端。另外的处理方法是只处理在给定时间内真正要进行通信的客户端。
  这是asyncore/asynchat框架采用的方法,这种功能的基础是select函数,如果poll函数可用,那也可以是它,这两个函数都来自select模块。其中poll函数的伸缩性要更好,但只能用在UNIX系统中。
  Select函数有3个序列作为它的必选参数,还有一个可选的超时时间作为第4个参数。这3个序列是套接字文件描述符,用于输入、输出以及异常情况。如果没有给定超时时间,select会阻塞,处于等待状态,直到一个文件描述符已经为行动做好了准备;如果给定超时时间,select最多阻塞给定的超时时间;如果给定的超时时间是0,select就不阻塞。Select的返回值是3个序列,一个长度为3的元组,每个代表相应参数的一个活动子集。

  1. import socket, select
  2.  
  3. s = socket.socket()
  4.  
  5. host = socket.gethostname()
  6. port = 1234
  7. s.bind((host, port))
  8.  
  9. s.listen(5)
  10. inputs = [s]
  11. while True:
  12. rs, ws, es = select.select(inputs, [], [])
  13. for r in rs:
  14. if r is s:
  15. c, addr = s.accept()
  16. print 'Got connection from', addr
  17. inputs.append(c)
  18. else:
  19. try:
  20. data = r.recv(1024)
  21. disconnected = not data
  22. except socket.error:
  23. disconnected = True
  24. if disconnected:
  25. print r.getpeername(), 'disconnected'
  26. inputs.remove(r)
  27. else:
  28. print data

  poll方法使用起来比select简单。在调用poll时,会得到一个poll对象。然后使用poll对象的register方法注册一个文件描述符(或者是带有fileno方法的对象)。注册后可以使用unregister方法移除注册的对象。注册完套接字对象之后可以调用poll方法(带有一个可选的超时时间参数)并得到一个(fd, event)格式列表(可能是空的),其中fd是文件描述符,event则告诉你发生了什么。event对象是一个位掩码,可以使用按位与操作来判断事件的类型.
select模块中的polling事件常量
事件名         描述
POLLIN       读取来自文件描述符的数据
POLLPRI       读取来自文件描述符的紧急数据
POLLOUT      文件描述符已经准备好数据,写入时不会发生阻塞
POLLERR        与文件描述符有关的错误情况
POLLHUP     挂起,连接丢失
POLLNVAL   无效请求,连接没有打开

  1. import socket, select
  2.  
  3. s = socket.socket()
  4.  
  5. host = socket.gethostname()
  6. port = 1234
  7. s.bind((host, port))
  8.  
  9. fdmap = {s.fileno(): s}
  10.  
  11. s.listen(5)
  12. p = select.poll()
  13. p.register(s)
  14. while True:
  15. events = p.poll()
  16. for fd, event in events:
  17. if fdmap[fd] is s:
  18. c, addr = s.accept()
  19. print 'Got connection from', addr
  20. p.register(c)
  21. fdmap[c.fileno()] = c
  22. elif event & select.POLLIN:
  23. data = fdmap[fd].recv(1024)
  24. if not data: # No data -- connection closed
  25. print fdmap[fd].getpeername(), 'disconnected'
  26. p.unregister(fd)
  27. del fdmap[fd]
  28. else:
  29. print data

12、Python-网络编程的更多相关文章

  1. Python 网络编程(二)

    Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单 ...

  2. Python 网络编程(一)

    Python 网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. ...

  3. python网络编程05 /TCP阻塞机制

    python网络编程05 /TCP阻塞机制 目录 python网络编程05 /TCP阻塞机制 1.什么是拥塞控制 2.拥塞控制要考虑的因素 3.拥塞控制的方法: 1.慢开始和拥塞避免 2.快重传和快恢 ...

  4. Python网络编程基础|百度网盘免费下载|零基础入门学习资料

    百度网盘免费下载:Python网络编程基础|零基础学习资料 提取码:k7a1 目录: 第1部分 底层网络 第1章 客户/服务器网络介绍 第2章 网络客户端 第3章 网络服务器 第4章 域名系统 第5章 ...

  5. Python网络编程基础 PDF 完整超清版|网盘链接内附提取码下载|

    点此获取下载地址提取码:y9u5 Python网络编程最好新手入门书籍!175个详细案例,事实胜于雄辩,Sockets.DNS.Web Service.FTP.Email.SMTP.POP.IMAP. ...

  6. Python网络编程之网络基础

    Python网络编程之网络基础 目录 Python网络编程之网络基础 1. 计算机网络发展 1.1. OSI七层模型 1.2. 七层模型传输数据过程 2. TCP/IP协议栈 2.1 TCP/IP和O ...

  7. Python学习(22)python网络编程

    Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...

  8. Day07 - Python 网络编程 Socket

    1. Python 网络编程 Python 提供了两个级别访问网络服务: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口 ...

  9. python网络编程-01

    python网络编程 1.socket模块介绍 ①在网络编程中的一个基本组件就是套接字(socket),socket是两个程序之间的“信息通道”. ②套接字包括两个部分:服务器套接字.客户机套接字 ③ ...

  10. 《Python网络编程》学习笔记--使用谷歌地理编码API获取一个JSON文档

    Foundations of Python Network Programing,Third Edition <python网络编程>,本书中的代码可在Github上搜索fopnp下载 本 ...

随机推荐

  1. C# 通过ImportNode AppendChild方法合并XmlDocument,XML转为DataTable

    var doc1 = new XmlDocument(); var doc2 = new XmlDocument(); XmlNode root1 = doc1.DocumentElement; do ...

  2. android studio 添加到项目库中的项目

    工程-对-new module-Android Library-module name和package name 它应该在同一个库被引入. 然后在该文件夹replace新的library 在gradl ...

  3. C编程的指针涛 ---第九笔记

    //这里说的是一个指针,指向算法的应用 //直接排序 //每个排序算法是指针指向的每个元件的特性的方便的交流 //这里的基本思想是,处理的记录的排序n - 1第二选择. //第i次操作选择i大(小)的 ...

  4. 通过 C# 代码操作 Google 日历

    原文:通过 C# 代码操作 Google 日历 本文主题 借助 Google .NET APIs Client Library,通过 C# 代码在 Google 日历中创建会议邀请. 本文背景 最近, ...

  5. openSUSE13.1安装Nodejs并更新到最新版

    软件源中直接安装Nodejs即可 sudo zypper in nodejs 查看nodejs版本 sincerefly@linux-utem:~> node --version v0.10.5 ...

  6. Ping域名惊现65.49.2.178

    --- 昨天新建的博,早晨起来进去看看,发现无法访问.这… 排错开始,ping域名出现如上图所示结果,请求超时…哪里的问题呢 有时常识是害人的,想起了前两月群里也有人说本地无法访问自己网站,别人能访问 ...

  7. Java中“==”和equals()方法

    这是在Thinking in Java中看到的. 第一个程序 public class Exponents { public static void main(String []args){ Inte ...

  8. OCP-1Z0-051-题目解析-第1题

    1. View the Exhibit and examine the structure of the SALES, CUSTOMERS, PRODUCTS, and TIMES tables. T ...

  9. firefox os 该设备呼叫移动开发

    1)话筒 权限:telephony api:navigator.moztelephony 参考链接:https://wiki.mozilla.org/WebAPI/WebTelephony 2) 扬声 ...

  10. 在SSIS中使用自定义的DLL文件

    原文:在SSIS中使用自定义的DLL文件 步骤1.开发dll(需要签名) using System;using System.Collections.Generic;using System.Text ...