HTTP协议、web静态服务器-并发服务器
HTTP协议简介
在web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来,而浏览器和服务器之间的传输协议是HTTP(超文本传输协议)
测试:
- 安装好Chrome浏览器后,打开Chrome,在菜单中找到开发者工具,然后就可以显示开发者工具
Element显示网页的结构,Network显示浏览器和服务器的通信
- 点Network,确保第一个小红灯亮着,Chrome就会记录所有浏览器和服务器之间的通信:
HTTP协议的分析
浏览器请求
当我们在地址栏输入www.sina.com时,浏览器将显示新浪的首页。在这个过程中,浏览器都干了哪些事情呢?通过Network的记录,我们就可以知道。在Network中,找到www.sina.com那条记录,点击,右侧将显示Request Headers,点击右侧的view source,我们就可以看到浏览器发给新浪服务器的请求:
说明:
最主要的是前两行的分析,第一行:
GET表示一个读取请求,将从服务器获得网页数据,/表示URL的路径,/就表示首页,最后的HTTP/1.1表示HTTP协议的版本是1.1,目前HTTP协议的版本是1.1,
第二行表示请求的域名是www.sina.com。如果一台服务器有多个网站,服务器就需要通过Host来区分浏览器请求的是哪个网站
User-Agent表示的是服务器允许传输所对应的浏览器及条件
Acccept表示接受的网页的格式
服务器响应
继续往下找到Response Headers,点击view source,显示服务器返回的原始响应数据:
HTTP响应分为Header和Body两部分(Body是可选项),我们在Network中看到的Header最重要的几行如下:
HTTP/1.1 200 OK
200表示一个成功的响应,后面的OK是说明。
如果返回的不是200,那么往往有其他的功能,例如
- 失败的响应有404 Not Found:网页不存在
- 500 Internal Server Error:服务器内部出错
…等等…
Content-Type: text/html
Content-Type指示响应的内容,这里是text/html表示HTML网页。
请注意,浏览器就是依靠Content-Type来判断响应的内容是网页还是图片,是视频还是音乐。浏览器并不靠URL来判断响应的内容,所以,即使URL是
http://www.baidu.com/meimei.jpg
,它也不一定就是图片。
HTTP响应的Body就是HTML源码,我们在菜单栏选择“视图”,“开发者”,“查看网页源码”就可以在浏览器中直接查看HTML源码:
浏览器解析过程
当浏览器读取到新浪首页的HTML源码之后,它会解析HTML,显示页面,然后根据HTML里面的各种链接,再发送HTTP请求给新浪服务器,拿到相应的图片、视频、Flash、Javascript脚本、CSS等各种资源,最终显示的是一个完整的界面;所以我们能在Network下面看到很多额外的HTTP请求
Web静态服务器-1-显示固定的界面
#coding=utf-8
import socket
def handle_client(client_socket):
"为一个客户端进行服务"
recv_data = client_socket.recv(1024).decode("utf-8")
request_header_lines = recv_data.splitlines()
for line in request_header_lines:
print(line)
# 组织相应 头信息(header)
response_headers = "HTTP/1.1 200 OK\r\n" # 200表示找到这个资源
response_headers += "\r\n" # 用一个空的行与body进行隔开
# 组织 内容(body)
response_body = "hello world"
response = response_headers + response_body
client_socket.send(response.encode("utf-8"))
client_socket.close()
def main():
"作为程序的主控制入口"
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置当服务器先close 即服务器端4次挥手之后资源能够立即释放,这样就保证了,下次运行程序时 可以立即绑定7788端口
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("", 7788))
server_socket.listen(128)
while True:
client_socket, client_addr = server_socket.accept()
handle_client(client_socket)
tcp_server_socket.close()
if __name__ == "__main__":
main()
打开浏览器,输入‘127.0.0.1:7788’,然后在浏览器就会出现一个设定好的固定网页
TCP的三次握手和四次挥手
要进行三次握手的目的是在建立连接的时候确定收发双方都已经准备好资源进行收发数据了;首先客户端向服务器发送一个数据J(SYN表示请求,ACK表示应答),如果服务器也准备好了那么就将收到的数据进行加一操作,并且同时也传输一个数字K,客户端收到消息确定服务端已经准备好了,将K加一并传给服务器告诉服务器我也已经准备好了;然后connect解堵塞,客户端和服务器连接之后进行数据传输
如果客户端操作完成了,不会再需要与服务端进行通信;首先客户端主动关闭,向服务器发送FIN数据包,表示关闭发送,接着服务器端收到消息后将序号加一,表示关闭接收;当服务器向客端传输的数据的过程结束之后,服务器端会调用close,向客户端发送FIN,客户端收到消息后,将接收序号加一传回给服务器,至此服务器端和客户端都关闭了自己的收发功能
web静态服务器-2-显示需要的概念
#coding=utf-8
import socket
import re
def handle_client(client_socket):
"为一个客户端进行服务"
recv_data = client_socket.recv(1024).decode('utf-8', errors="ignore")
request_header_lines = recv_data.splitlines()
for line in request_header_lines:
print(line)
http_request_line = request_header_lines[0]
# 正则表达式中如果^是在整个正则表达式的开始,那么表示‘开始’的作用;如果这个是在句子中间,那么代表的是一个‘否定’的含义
get_file_name = re.match("[^/]+(/[^ ]*)", http_request_line).group(1)
print("file name is ===>%s" % get_file_name) # for test
# 如果没有指定访问哪个页面。例如index.html
# GET / HTTP/1.1
if get_file_name == "/":
get_file_name = DOCUMENTS_ROOT + "/index.html"
else:
get_file_name = DOCUMENTS_ROOT + get_file_name
print("file name is ===2>%s" % get_file_name) #for test
try:
f = open(get_file_name, "rb")
except IOError:
# 404表示没有这个页面
response_headers = "HTTP/1.1 404 not found\r\n"
response_headers += "\r\n"
response_body = "====sorry ,file not found===="
else:
response_headers = "HTTP/1.1 200 OK\r\n"
response_headers += "\r\n"
response_body = f.read()
f.close()
finally:
# 因为头信息在组织的时候,是按照字符串组织的,不能与以二进制打开文件读取的数据合并,因此分开发送
# 先发送response的头信息
client_socket.send(response_headers.encode('utf-8'))
# 再发送body
client_socket.send(response_body)
client_socket.close()
def main():
"作为程序的主控制入口"
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("", 7788))
server_socket.listen(128)
while True:
client_socket, clien_cAddr = server_socket.accept()
handle_client(client_socket)
#这里配置服务器
DOCUMENTS_ROOT = "./html"
if __name__ == "__main__":
main()
还没有评论,来说两句吧...