#!/usr/bin/env python
#coding=utf-8
from socket import *
import os
import re
#host是本机地址,serverPort是端口号,程序运行后,在浏览器中输入 127.0.0.1:6699/index.html 即可访问主页
host = '127.0.0.1'
serverPort = 6699
#创建了服务器的套接字,其中AF_INET表示使用的是IPV4协议,SOCKER_STREAM表示使用的是TCP套接字
serverSocket = socket(AF_INET , SOCK_STREAM)
#表示将服务端端口与套接字连接起来
serverSocket.bind((host , serverPort))
#让服务器聆听TCP连接,参数为请求连接的最大数目
serverSocket.listen(5)
f = open('index.html' , 'r')
index_content = '''
HTTP/1.1 200 ok
Content-Type: text/html
'''
#index_conten是服务器响应文件的报文头,第一位是HTTP协议,然后是状态 200 ok
#如果没有请求到文件,则替换 200 ok 为 404 Not Found。
#Content-Type 指的是文件类型,你要回传html类型的文件。就是text/html,如果是png图片,则是image/png 具体根据文件格式去查找相应名称
#一定一定要注意格式,不能有变化,否则浏览器不能正确理解文件类
index_content += f.read()
#将报文头加到文件里面
f.close()
f = open('css/style.css' , 'r')
css_content = '''
HTTP/1.1 200 ok
Content-Type: text/css
'''
css_content += f.read()
f.close()
print'Servering port %d '% serverPort
#一直循环等待请求连接
while 1 :
#当有客户机响应时,则建立TCP连接
connectionSocket,addr = serverSocket.accept()
#sentence收到的是客户发送请求的报文,里面有请求方法,请求文件等
sentence = connectionSocket.recv(1024)
print sentence
#格式类似于:
#GET /favicon.ico HTTP/1.1
#Host: 127.0.0.1:6699
#User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
#这样对报文进行拆分,第0个就是请求方法 如 GET POST
method = sentence.split(' ')[0]
print method
#观察到连接建立后,浏览器会发一个空的报文过来,此时就没有请求文件
#于是使用try来捕获异常,
try:
scr = sentence.split(' ')[1]
except:
print 'waiting next connection'
continue
if method == 'GET':
if scr == '/index.html' or scr == '/':
print 'index response successfully\n\n'
content = index_content
elif scr == '/css/style.css':
print 'css response successfully\n\n'
content = css_content
#使用正则来匹配用户输入网页,如果html结尾,就去文件中查找有没有该文件,有则加上报文头,传回客户 。没有则返回404报文
elif re.match(r'/(.*).html' , scr):
path = scr.split('/')[1]
content = '''
HTTP/1.1 200 ok
Content-Type: text/html
'''
try:
f = open(path , 'rb')
content += f.read()
f.close()
except :
print 'not find %s',scr
content = '''
HTTP/1.1 404 Not Found
Content-Type: text/html
'''
#匹配.png文件,失败返回404报文头
elif re.match(r'/images/(.*).png' , scr):
path = scr.split('/')[2]
content = '''
HTTP/1.1 200 ok
Content-Type: image/png
'''
try:
path = 'images/'+path
f = open(path , 'rb')
content += f.read()
f.close()
print 'png response successfully\n\n'
except :
print 'not find %s',scr
content = '''
HTTP/1.1 404 Not Found
Content-Type: image/png
'''
#匹配.jpg文件,失败返回404报文头
elif re.match(r'/images/(.*).jpg' , scr):
path = scr.split('/')[2]
content = '''
HTTP/1.1 200 ok
Content-Type: image/jpg
'''
try:
path = 'images/'+path
f = open(path , 'rb')
content += f.read()
f.close()
print 'jpg response successfully\n\n'
except:
print 'not find %s',scr
content = '''
HTTP/1.1 404 Not Found
Content-Type: image/jpg
'''
#最后,若是输入了非法URL,则直接返回404
else :
print 'not find %s',scr
content = '''
HTTP/1.1 404 Not Found
Content-Type: text/html
'''
#将文件发送出去,并且关闭连接
connectionSocket.sendall(content)
connectionSocket.close()
注意事项
1、在书写报文头的时候,一定要按格式规范,否则可能出现图片加载不出来、html文件只显示源代码等情况
2、要是没有请求到文件,则要返回404,不能直接忽视掉,因为客户会一直请求这个文件
3、有时会出现./favicon.ico的请求,原因是浏览器会根据写在HTML<head>标签里面的收藏夹图标进行查找,可能会查找不到,这时候要返回404