【郑州校区】HTTP手记 ---------------------tcp/ip模型和osi模型---------------------
tcp/ip协议模型 osi模型
应用层 应用层
表示层
会话层
传输层 传输层
网络层 网络层
链路层 数据链路层
物理层 ---------------------交换机---------------------
1、网络交换机介绍:
网络交换机(又称“网络交换器”),是一个扩大网络的器材,能为子网络中提供更多的连接端口,以便连接更多的计算机 具有性能价格比高、高度灵活、相对简单、易于实现等特点 以太网技术已成为当今最重要的一种局域网组网技术,网络交换机也就成为了最普及的交换机 2、交换机的作用:
转发过滤:当一个数据帧的目的地址在MAC地址表中有映射时,它被转发到连接目的节点的端口而不是所有端口(如该数据帧为广播帧则转发至所有端口)
学习功能:以太网交换机了解每一端口相连设备的MAC地址,并将地址同相应的端口映射起来存放在交换机缓存中的MAC地址表中 ---------------------路由器---------------------
1. 路由器简介
路由器(Router)又称网关设备(Gateway)是用于连接多个逻辑上分开的网络 所谓逻辑网络是代表一个单独的网络或者一个子网。当数据从一个子网传输到另一个子网时,可通过路由器的路由功能来完成 具有判断网络地址和选择IP路径的功能 不在同一网段的pc,需要设置默认网关才能把数据传送过去 通常情况下,都会把路由器默认网关
当路由器收到一个其它网段的数据包时,会根据“路由表”来决定,把此数据包发送到哪个端口;路由表的设定有静态和动态方法
每经过一次路由器,那么TTL值就会减一 ---------------------模拟进行客户端、DNS服务器、HTTP服务器实现---------------------
---------------------HTTP请求的流程---------------------
步骤1:浏览器首先向服务器发送HTTP请求 方法:GET还是POST,GET仅请求资源,POST会附带用户数据; 路径:/full/url/path; 以及其他相关的Header; 如果是POST,那么请求还包括一个Body,包含用户数据
步骤2:服务器向浏览器返回HTTP响应
响应代码:200表示成功,3xx表示重定向,4xx表示客户端发送的请求有错误,5xx表示服务器端处理时发生了错误; 响应类型:由Content-Type指定; 以及其他相关的Header; 相应长度:由Content-Length:755 通常服务器的HTTP响应会携带内容,也就是有一个Body,包含响应的内容,网页的HTML源码就在Body中。
步骤3:如果浏览器还需要继续向服务器请求其他资源,比如图片,就再次发出HTTP请求
Web采用的HTTP协议采用了非常简单的请求-响应模式,从而大大简化了开发。当我们编写一个页面时,我们只需要在HTTP请求中把HTML发送出去,不需要考虑如何附带图片、视频等,浏览器如果需要请求图片和视频,它会发送另一个HTTP请求,因此,一个HTTP请求只处理一个资源(此时就可以理解为TCP协议中的短连接,每个链接只获取一个资源,如需要多个就需要建立多个链接)
---------------------tcp协议三次握手和四次挥手--------------------- 三次握手 四次握手 ---------------------epoll和进程结合模拟实现一个简单的http服务器--------------------- [AppleScript] 纯文本查看 复制代码 1 #coding=utf-8
2
3 #引用对应的数据包
4 from socket import *
5
6 import sys
7
8 import re
9
10 import select
11
12 import multiprocessing
13
14 from time import sleep
15
16 #创建全局变量
17 #创建一个epoll对象
18 epoll=select.epoll()
19
20 #创建两个字典
21 #字典1:根据套接字对应的文件标识符对应的套件字
22 connection={}
23
24 #字典2:根据套建字对应的文件表示符对应的ip和端口元祖信息
25 address={}
26
27
28 #运行进程
29 def runProc(recvData,soc,addr,fd):
30 #引用全局变量进行处理
31 global epoll
32 global connection
33 global address
34
35 #使用正则,获取到对应的要读取的文件名
36 fileName=re.search("GET (.*) HTTP",recvData).group(1)
37
38 print(fileName)
39
40 #调用函数获取到处理后的地址
41 fileName=getPath(fileName)
42
43 #获取文件后缀名,进行相应头文件的准备
44 fileExt=fileName[fileName.rindex('.')+1:]
45
46 print ("02-文件的后缀名--:"+fileExt)
47
48 #存储响应报文
49 httpHead=''
50
51 if fileExt.lower() in ['html','css']:
52 #制定文件的读取操作
53 fil=open(fileName,'r')
54
55 #读取制定文件中的数据信息
56 htmlText=fil.read()
57
58 #关闭对应的文件对象
59 fil.close()
60
61 #创建变量:存储有效的响应头文件
62 httpHead="HTTP/1.1 200 OK \r\n Content-Type:text/"+fileExt.lower()+" \r\n\r\n"
63 #进行数据的回复操作
64 soc.send(httpHead+htmlText)
65
66 #将该套接字从epoll中注销
67 epoll.unregister(fd)
68
69 #从字典中进行排除
70 del connection[fd]
71 del address[fd]
72
73 soc.close()
74
75 print("%s-------end"%fileExt)
76
77 elif fileExt.lower() in ['png','jpg','gif']:
78 #制定文件的读取操作
79 fil=open(fileName,'rb')
80
81 #读取制定文件中的数据信息
82 htmlText=fil.read()
83
84 #关闭对应的文件对象
85 fil.close()
86 httpHead="HTTP/1.1 200 ok \r\n Content-Type:image/"+fileExt.lower()+" \r\n\r\n"
87
88 #print(fileExt.lower())
89 #print(htmlText)
90
91 #sleep(2)
92
93 #进行数据的回复操作
94 soc.send(httpHead+htmlText)
95
96 #将该套接字从epoll中注销
97 epoll.unregister(fd)
98
99 #从字典中进行排除
100 del connection[fd]
101 del address[fd]
102
103 soc.close()
104
105 print("%s------end"%fileExt.lower())
106
107
108 #函数:文件路径
109 def getPath(fileName):
110 #变量存储文件地址;
111 filePath=''
112
113 print(fileName)
114
115 #根目录,默认指向./html/Index.html
116 if fileName[0:4]=='/html':
117 filePath='.'+fileName
118 else:
119 filePath='./html'+fileName
120
121 print("01-获取到对应的文件路径--:%s"%filePath)
122
123 return filePath
124
125 #主函数
126 def main():
127 #引用全局变量进行处理
128 global epoll
129 global connection
130 global address
131
132 #创建服务器套接字
133 tcpSerSoc=socket(AF_INET,SOCK_STREAM)
134
135 tcpSerSoc.setsockopt(SOL_SOCKET, SO_REUSEADDR,1)
136
137 #进行对应数据的绑定
138 tcpSerSoc.bind(("",int(sys.argv[1])))
139
140 #tcp服务器开启被动监听状态
141 tcpSerSoc.listen(10)
142
143 #使用epoll对服务器套接字在操作系统中进行注册
144 epoll.register(tcpSerSoc.fileno(),select.EPOLLIN|select.EPOLLET)
145
146 #提示开启对应的服务
147 print("-----开启对应的HTTP服务-----")
148
149 #循环,对客户端传递过来的数据进行处理
150 while True:
151 #通过操作系统获取到要进行数据处理的套接字
152 epollList=epoll.poll()
153
154 #遍历所有的套接字进行相应的处理
155 for fd,event in epollList:
156 #判断是否为服务器的套接字
157 if fd==tcpSerSoc.fileno():
158 #接收客户端对应的数据信息
159 newSocket,destAddr= tcpSerSoc.accept()
160
161 print("客户端(%s)以接入HTTP服务器"%str(destAddr))
162
163 #将对应的数据向字典中进行存储
164 connection[newSocket.fileno()]=newSocket
165 address[newSocket.fileno()]=destAddr
166
167 #将新的套接字通过epoll向操作系统中进行注册
168 epoll.register(newSocket.fileno(),select.EPOLLIN|select.EPOLLET)
169
170 elif event==select.EPOLLIN:
171 #拿到对应的套接字和ip端口
172 soc=connection[fd]
173 addr=address[fd]
174
175 #进行客户端数据对应的接收操作
176 recvData=soc.recv(1024)
177
178 #判断接受的数据是否为空:如果为空表示客户下线
179 if len(recvData)>0:
180 #启动一个新的socked进程
181 p=multiprocessing.Process(target=runProc,args=(recvData,soc,addr,fd))
182 p.start()
183 p.join()
184
185 soc.close()
186 else:
187
188 print("客户(%s)以离开"%str(addr))
189
190 #将该套接字从epoll中注销
191 epoll.unregister(fd)
192
193 soc= connection[fd]
194
195 #从字典中进行排除
196 del connection[fd]
197 del address[fd]
198
199 #关闭该套接字
200 soc.close()
201
202 #关闭服务器套接字
203 tcpSerSoc.close()
204
205
206 #程序入口
207 if __name__=='__main__':
208 main()
|