您的位置:首页 > 理论基础 > 计算机网络

利用python编写设计多线程web服务器(计算机网络_自顶向下第六版_第二章1和4的编程作业)

2017-11-26 23:37 811 查看
                                        利用python编写设计多线程web服务器

一、    程序实现的功能:

 1.向服务器请求特定文件,从服务器文件系统读取请求的文件,并创建一个由请求的文件的html内容组成的HTTP响应报文反馈给浏览器并显示出来  



(从后台可以看到请求的文件的内容)



(浏览器端显示的登录成功的界面)

2.多线程



(多个客户端访问服务器时,都可以并发地访问,通过后台观察打印出的地址可以发现服务器已经接收到了多个客户端的访问,并且服务器为每个客户端联系时均建立了连接套接字)



(从浏览器访问可以看出,可以同时打开两个页面访问本地服务器,其中服务器的端口号为40000)

<
4000
p>3.异常检测
访问服务器不存在的路径,如下图所示例子



浏览器端会返回一个路径不存在的页面:



 

二、 源代码:

1.主程序:



#*************************************#
#*** python 多线程web服务器的设计   ****#
#*** Author wobeatit              ****#
#*** Python 版本:3.6.2            ****#
#*************************************#

#-*- coding: utf-8 -*-
from socket import *
import threading #引入线程模块
import os

#访问服务器失败返回的html页面
FAIL_PAGE="""
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="content-type" content="text/html"; charset="utf-8"/>
</head>
<body>
<h2>所访问的路径不存在!</h2>
</br></br>
<!--打开网页图片-->
<img src="http://img.bitscn.com/upimg/allimg/c160324/145Wb34E21Z-191918.jpg" width="400px"/>
</br></br>
<a href="http://blog.csdn.net/wobeatit/article/details/78641032">我的博客</a>
</body>
</html>
"""

HOST="" #HOST 变量是空白的,这是对 bind()方法的标识,表示它可以使用任何可用的地址  #此程序在什么主机上运行,就会为该主机的IP地址
PORT=40000  #随机的端口号,并且该端口号似乎没有被使用或被系统保留
ADDR=(HOST,PORT) #地址=主机名+端口号

def Server(tcpClisock,addr): #针对线程使用编写的函数
HOME_DIR="D:/Anaconda/lib" #程序的文件编译路径
BUFSIZE=1024 #将缓冲区大小设置为 1KB。listen()方法的参数是在连接被转接或拒绝之前,传入连接请求的最大数
print('connected from:',addr)
rec = tcpClisock.recv(BUFSIZE)
data=rec.decode()
print(data) #将网页浏览返回的响应报文打印出来
print("***************************************************\n")

index=4;#检索文件的搜索路径
while data[index]!=' ':  #找到路径
index=index+1
direction=HOME_DIR+data[4:index] #拼接出完整的路径
if os.path.exists(direction):   #如果路径存在
file=open(direction+'/success.html')    #打开路径中的文件,此路径文件名每台电脑不一样,要自己找到电脑的os.path路径,再在其中写一个文件html文件

SUCCESS_PAGE="HTTP/1.1 200 OK\r\n\r\n"+file.read() #构造成功报文反馈给服务器,该文件写在learn_2.html文件中
print(SUCCESS_PAGE)
tcpClisock.sendall(SUCCESS_PAGE.encode()) #返回给客户端浏览器成功的页面
#sendall 函数只可发送字节类型,对字符串数据进行转换
tcpClisock.close()#关闭专门针对一个客户机程序创建的新套接字
else:
#如果路径不存在
tcpClisock.sendall(FAIL_PAGE.encode()) #返回给客户端浏览器成功的页面
#sendall 函数只可发送字节类型,对字符串数据进行转换
tcpClisock.close()#关闭专门针对一个客户机程序创建的新套接字

if __name__ =='__main__':
HOST="" #HOST 变量是空白的,这是对 bind()方法的标识,表示它可以使用任何可用的地址  #此程序在什么主机上运行,就会为该主机的IP地址
PORT=40000  #随机的端口号,并且该端口号似乎没有被使用或被系统保留
ADDR=(HOST,PORT) #地址=主机名+端口号
tcpSersock=socket(AF_INET,SOCK_STREAM) #创建一个套接字对象
tcpSersock.bind(ADDR) #将套接字绑定到服务器地址  相当于欢迎套接字,且绑定的是源ip地址以及源端口号。始终欢迎别的套接字的申请接入
tcpSersock.listen(5) #启用服务器的监听,调用参数是在连接被转接或拒绝之前,传入连接请求的最大数
#此处说明允许传入链接请求数为5
print("waiting for connection......\n")
while True:  #进入无限循环
tcpClisock,addr = tcpSersock.accept()
#调用 accept()函数之后,就开启了一个简单的(单线程)服务器,它会等待客户端的连接。
#默认情况下,accept()是阻塞的,这意味着执行将被暂停,直到一个连接到达
#当一个传入的请求到达时,服务器会创建一个新的通信端口来直接与客户端进行通信,再次空出主要的端口
#使用新的客户端套接字能够空出主线(原始服务器套接字)
#以使其能够接受新的客户端连接。
thread = threading.Thread(target=Server, args=(tcpClisock, addr))
thread.start()#开始执行该线程

tcpSersock.close()#这种情况永远也不会碰到,因为在此程序中,服务器始终在一个无限循环中运行
#但如果写了一个处理程序,当一个处理程序检测到一些外部条件时,服务器就应该关闭。应该调用一个 close()方法关闭服务器的欢迎套接字


2.本地服务器中存储的显示成功页面的success.html文件内容:

<!DOCTYPEhtml>
<html>
<head>
<title></title>
<metahttp-equiv="content-type"content="text/html";charset="utf-8"/>
</head>
<body>
<h3>Connectto local web server!</h3>
<imgsrc="http://i2.sinaimg.cn/ent/m/c/2008-03-16/U2507P28T3D1949676F326DT20080316182933.jpg"width="200px"/>
</br>
<ahref="http://blog.csdn.net/wobeatit/article/details/78641032">MyCSDN</a>
</body>
</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: