1.tcp传输的问题
* 传输特征 recv send(发)
* 网络缓冲区 send --> 缓冲区 -->
* 沾包 (多次发送的内容,一条接收)
2.udp套接字编程
服务端: socket --》 bind--> recvfrom,sendto-->close
客户端: socket --》sendto,recvfrom--->close
3.socket模块函数,套接字属性
fileno()
getpeername()
setsockopt()
4.广播
5.http协议传输
* 什么是http协议,应用场景
* 基于http获取网页的大体流程
* http的请求
请求行:具体的请求类别和请求内容
GET / HTTP/1.1
请求类别 请求内容 协议版本
get pose head put delete
请求头 空行 请求体
---------------------------------------------homework----------------------------------------------------------------------------
一.Http协议(续)
1.Http响应(response)
[1]响应格式:响应行,响应头,空行,响应体
[2]响应行:反馈基本的响应情况
Http/1.1 200 0k
版本信息 响应码 附加信息说明
响应码:1xx 提示信息 表示请求被接受
2xx 表示响应成功
3xx 重定向,响应需要进一步操作
4xx 客户端错误
5xx 服务器错误
[3]响应头:对响应内容的描述
Content-Type:text/html
[4]空行
[5]响应体:响应的主体内容信息
1 from socket import * 2 3 #创建套接字 4 s = socket() 5 s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#对套接字设置为可以立即重用端口(绑定前) 6 print(s.getsockopt(SOL_SOCKET,SO_REUSEADDR)) 7 s.bind(('0.0.0.0',8000)) 8 s.listen(3) 9 10 c,addr = s.accept()#接收浏览器连接 11 print("Connect from",addr) 12 data = c.recv(4096)#浏览器发送请求 13 print(data) 14 #组织http相应 15 data = '''HTTP/1.1 200 ok 16 Content-Type:text/html 17 18 hello world 19 ''' 20 c.send(data.encode())#符合http响应格式 21 22 c.close() 23 s.close()
1 from socket import * 2 ''' 3 http server v1.0 4 接收浏览器请求 5 返回固定的响应内容 6 ''' 7 #处理客户端请求 8 def handleClient(connfd): 9 print("Request from",connfd.getpeername())#打印客户端 10 request =connfd.recv(4096)#接收http请求 11 #将request按行分割 12 request_lines = request.splitlines() 13 for line in request_lines: 14 print(line) 15 try: 16 f = open('shou.html') 17 except IOError: 18 response="HTTP/1.1 404 Not Fount\r\n" 19 response+="\r\n" 20 response+="****not found****" 21 else: 22 response="HTTP/1.1 200 OK\r\n" 23 response+="\r\n" 24 response+=f.read() 25 finally: 26 #将结果发送给浏览器 27 connfd.send(response.encode())#发 28 29 #创建套接字 30 def main(): 31 sockfd = socket() 32 sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#对套接字设置为可以立即重用端口(绑定前) 33 sockfd.bind(('0.0.0.0',8465)) 34 sockfd.listen(3) 35 print("listen to port 8000") 36 while True: 37 connfd,addr = sockfd.accept() 38 handleClient(connfd) #负责具体的请求处理 39 connfd.close() 40 41 if __name__=='__main__': 42 main()
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <title>无标题文档</title> 6 </head> 7 8 <body> 9 <img src="blueline.png" width="1839" height="11" /> 10 <table width="100%" height="136" border="1" align="center"> 11 12 13 <tr bgcolor="#0000A0" style="color:#CCC"> 14 <td width="41" height="50" align="center">排名</td> 15 <td width="211" align="center">图书名称</td> 16 <td width="89" align="center">图书类型</td> 17 <td width="67" align="center">书架</td> 18 <td width="145"align="center" >出版社</td> 19 <td width="109" align="center">作者</td> 20 <td width="91" align="center">借阅次数</td> 21 </tr> 22 <tr> 23 <td align="center" height="50">1</td> 24 <td align="center">Java2实用教程</td> 25 <td align="center">网络编程</td> 26 <td align="center">2-102-c</td> 27 <td align="center">清华大学出版社</td> 28 <td align="center">王国辉</td> 29 <td align="center">2</td> 30 </tr> 31 <tr> 32 <td align="center" height="50">2</td> 33 <td align="center">人类简史</td> 34 <td align="center">历史</td> 35 <td align="center">2-202-c</td> 36 <td align="center">九州出版社</td> 37 <td align="center">尤瓦尔.赫拉利</td> 38 <td align="center">1</td> 39 </tr> 40 <tr> 41 <td align="center" height="50">3</td> 42 <td align="center">物理界四大神兽</td> 43 <td align="center">科技</td> 44 <td align="center">2-102-a</td> 45 <td align="center">北京出版社</td> 46 <td align="center">芝诺</td> 47 <td align="center">1</td> 48 </tr> 49 <tr> 50 <td align="center" height="50">4</td> 51 <td align="center">虫洞</td> 52 <td align="center">科技</td> 53 <td align="center">2-201-a</td> 54 <td align="center">九州出版社</td> 55 <td align="center">罗森桥</td> 56 <td align="center">1</td> 57 </tr> 58 <tr> 59 <td align="center" height="50">5</td> 60 <td align="center">资治通鉴</td> 61 <td align="center">历史</td> 62 <td align="center">2-201-c</td> 63 <td align="center">九州出版社</td> 64 <td align="center">司马光</td> 65 <td align="center">1</td> 66 </tr> 67 <tr> 68 <td align="center" height="50">6</td> 69 <td align="center">曲艺杂谈</td> 70 <td align="center">历史</td> 71 <td align="center">1-103-b</td> 72 <td align="center">九州出版社</td> 73 <td align="center">王文华</td> 74 <td align="center">1</td> 75 </tr> 76 <tr> 77 <td align="center" height="50">7</td> 78 <td align="center">鱼羊野史</td> 79 <td align="center">历史</td> 80 <td align="center">1-101-</td> 81 <td align="center">九州出版社</td> 82 <td align="center">高晓松</td> 83 <td align="center">1</td> 84 </tr> 85 <tr> 86 <td align="center" height="50">8</td> 87 <td align="center">易中天中华史</td> 88 <td align="center">历史</td> 89 <td align="center">1-102-c</td> 90 <td align="center">九州出版社</td> 91 <td align="center">易中天</td> 92 <td align="center">1</td> 93 </tr> 94 <tr> 95 <td align="center">9</td> 96 <td align="center" height="50">细说大汉</td> 97 <td align="center">历史</td> 98 <td align="center">1-204-b</td> 99 <td align="center">九州出版社</td> 100 <td align="center">与海娣</td> 101 <td align="center">1</td> 102 </tr> 103 104 </table> 105 106 </body> 107 </html> 108
二.IO
[1]定义:在内存中数据交换的操作认为是IO操作
e.g. 和终端交互:input print
和磁盘交互:read write
和网络交互:recv send
IO密集型程序:在程序中执行中有大量IO操作,而cpu运算较少。消耗cpu少,耗时长
计算密集型程序:程序运行中计算较多,IO操作相对较少,CPU消耗多,执行速度快,几乎没有阻塞
[2]IO分类:阻塞IO,非阻塞IO,IO多路复用,IO异步IO
[3]阻塞IO
1.定义:在执行IO操作时如果执行条件不满足则阻塞.阻塞IO是IO的默认形态
2.效率:阻塞IO是效率很低的一种IO。但是由于逻辑简单所以是默认IO行为。
3.阻塞情况:
* 因为某种执行条件没有满足造成的函数阻塞
e.g. accept input recv
* 处理IO的时间较长产生的阻塞状态
e.g.网络传输,大文件读写
[4].非阻塞IO
1.定义:通过修改IO属性行为,使原本阻塞IO变为非阻塞的状态
2.设置套接字为非阻塞IO
sockfd.setblocking(bool)
功能:设置套接字为非阻塞IO
参数:默认为True,表示套接字IO阻塞;设置为False则套接字IO变为非阻塞
1 from socket import * 2 from time import sleep,ctime#访问当前时间 3 4 sockfd = socket() 5 sockfd.bind(('172.40.71.149',8888)) 6 sockfd.listen(3) 7 8 #设置非阻塞状态 9 sockfd.setblocking(False) 10 11 12 while True: 13 print("Waiting for connect...") 14 try: 15 connfd,addr = sockfd.accept() 16 except BlockingIOError: 17 sleep(2) 18 print("%s connect error"%ctime()) 19 continue 20 else: 21 print("Conect from",addr)
3.超时检测:设置一个最长的阻塞时间超过该时间后期不在
阻塞等待。
sockfd.settimeout(sec)
功能:设置套接字的超时时间
参数:设置的时间
select(xx,xx,xx,[timeout])
1 from socket import * 2 from time import sleep,ctime#访问当前时间 3 4 sockfd = socket() 5 sockfd.bind(('172.40.71.149',8888)) 6 sockfd.listen(3) 7 8 #设置非阻塞状态 9 # sockfd.setblocking(False) 10 11 #设置超市时间 12 sockfd.settimeout(10) 13 14 while True: 15 print("Waiting for connect...") 16 try: 17 connfd,addr = sockfd.accept() 18 except BlockingIOError: 19 sleep(2) 20 print("%s connect error"%ctime()) 21 continue 22 except timeout: 23 print("timeout.....") 24 else: 25 print("Conect from",addr)
[5]IO多路复用:
1.定义:同时监控多个Io事件,当那个IO事件准备就绪就执行那个IO事件。以此形成
可以同时处理多个IO行为,避免一个IO阻塞造成其他IO均无法执行,提高了IO的
执行效率
2.具体实现方案
select方法: Windows Linux unix
poll方法:Linux unix
epoll方法:Linux
3.python实现IO多路复用
import select
四.python 实现IO多路复用
1.select 方法(select模型下的select函数)
select(...)
select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)
||
^^
rs, ws, xs = select(rlist, wlist, xlist[,timeout])
功能L监控IO事件,阻塞等待IO事件发生
参数:rlist 列表 存放关注的等待发生的IO事件(不定)
wlist 列表 存放关注的要主动处理的IO事件(可以决定)
xlist 列表 存放关注的出现异常要处理的IO
timeout 超时时间 阻塞等待监控的IO(不报错)
返回值:
rs 列表 rlist中准备就绪的IO
ws 列表 wlist中准备就绪的IO
xs 列表 xlist中准备就绪的IO
2.select 实现tcp服务
1.将关注的IO放入对应的监控类别列表
2.通过select函数进行监控
3.遍历select 返回值列表,确定就绪IO事件
4.处理发生的IO事件
注意:1.wlist中如果存在IO事件中,则select立即返回给ws
2.处理IO过程中不要出现死循环占有服务端的情况
3.IO多路复用消耗资源较少,效率较高
1 from select import select 2 from socket import * 3 4 #1创建套接字作为关注的IO 5 s = socket() 6 s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) 7 s.bind(('0.0.0.0',8885)) 8 s.listen(5) 9 10 #2添加到关注列表 11 rlist = [s] 12 wlist = [] 13 xlist = [] 14 15 16 while True: 17 #3监控关注的IO 18 rs,ws,xs = select(rlist,wlist,xlist) 19 #4循环便利确定的IO 20 for r in rs: 21 #s就绪 有客户端请求连接 22 if r is s: 23 c,addr = s.accept()# 24 print("Connect from",addr)#表示有客户段连接 25 #将客户端连接套接字加入关注 26 rlist.append(c) 27 #某个客户端发消息则c就绪 28 else: 29 data = r.recv(1024) 30 if not data: 31 rlist.remove(r) 32 r.close() 33 continue 34 print("Receive:",data.decode()) 35 r.send(b"OK,Thanks") 36 37 38 for w in ws: 39 pass 40 for x in xs: 41 pass
1 from socket import * 2 3 #创套接字 4 sockfd = socket() 5 6 #发起连接 7 server_addr = ('172.40.71.149',8885) 8 sockfd.connect(server_addr) 9 10 #收发消息 11 while True: 12 #发 13 data = input(">>") 14 sockfd.send(data.encode()) 15 if not data: 16 break 17 #收 18 data = sockfd.recv(1024) 19 print("From server:",data.decode()) 20 21 #关闭套接子 22 sockfd.close() 23
四.位运算
定义:将整数转换为二进制,按二进制位进行运算
运算类型: & 按位与
| 按位或
^ 按位异或
<< 左移
>> 右移
e.g. 14 --> 01110
19 --> 10011
14 & 19 00010 2 一零则零
14 | 19 11111 31 一1则1
14 ^ 19 11101 29 相同则0,不同为1
14 << 2 0111000 56 向左移动2位,低位补零
14 >> 2 11 3 向右移动,去掉低位
作业:1.编程:使用select完成一个服务程序,要求从客户端发来的信息写入到一个文件中,
同时监控服务端的终端输入,将输入内容也写入该文件
监控sys.stdin
2.丰富一下http协议的相关内容
3.复习函数的使用(函数设计,函数传参)