作为服务器,就是收到客户端的请求,发送数据。其实前面我已经做了几个服务器的例子,但只是知其然,不知其所以然。虽然确实实现了客户端和服务端的通信,可是好像和我平时真正访问互联网不一样。
知道了解到html的本质,才真的懂了一点,很多困惑也解开了。为了使普通字或者数据更加丰富,有一定格式,于是有了超文本标记语言这么一说。平时当我们访问网络时,服务器返回的数据已网页形式展示,其实和我之前做的事差不多,只是数据格式不同(以前是纯文本,现在是html格式)
现在再次搭建一个本地服务器,返回的数据已静态的网页展示。
整个结构和前面的一样,只是返回数据那里有点区别。
一,第一步创建套接字。(想可以多人访问,所以先导入多线程和套接字)
from socket import *
from threading import Thread
server = socket(AF_INET,SOCK_STREAM) #创建套接字
server.bind(("",7788)) #绑定端口
server.listen(5) #设置监听
第二步,创建新的套接字给多线程。(处理客户端的请求)
while True:
client_socket , ip_port = server.accept() #等待客户端连接
print("%s:%s>>>正在连接中。。。"%ip_port) #显示那个在连接
childthread = Thread(target=recvsocket , args=(client_socket,)) #分配给线程处理
childthread.start() #子线程启动,主线程返回继续等待另一个客户端的连接
第三步,线程处理客户的请求并返回结果。(这个例子返回是简单的固定的内容,不是调用html文件)
def recvsocket(client_socket):
recvdata = client_socket.recv(1024)
print("request data:", recvdata) #这里可以看到客户端的请求信息
response_start_line = "HTTP/1.1 200 OKrn" #按照网页的响应报头格式编写响应信息
response_headers = "Server: pycharm serverrn"
response_boby = "hello world" #响应内容
response = response_start_line + response_headers + "rn" + response_boby
client_socket.send(response.encode("utf-8"))
client_socket.close()
将片段整理一下,就是这样。
#coding = utf-8
from socket import *
from threading import Thread
def recvsocket(client_socket):
recvdata = client_socket.recv(1024)
print("request data:", recvdata) #这里可以看到客户端的请求信息
response_start_line = "HTTP/1.1 200 OKrn" #按照网页的响应报头格式编写响应信息
response_headers = "Server: pycharm serverrn"
response_boby = "hello world" #响应内容
response = response_start_line + response_headers + "rn" + response_boby
client_socket.send(response.encode("utf-8"))
client_socket.close()
if __name__ == '__main__':
server = socket(AF_INET, SOCK_STREAM)
server.bind(("", 7788))
server.listen(5)
while True:
client_socket , ip_port = server.accept() #等待客户端连接
print("%s:%s>>>正在连接中。。。"%ip_port) #显示哪个在连接
childthread = Thread(target=recvsocket , args=(client_socket,)) #分配给线程处理
childthread.start() #子线程启动,主线程返回继续等待另一个客户端的连接
访问结果
这个样子就有点像我平时访问网页的样子了,原来就是发送的格式不太一样。
如果想返回的网页不是现场编写的,而是根据客户端的请求调用已编写好的网页该怎么编写呢?
其实还是差不多,只是将响应的内容换成想调用的文件。
#coding = utf-8
from socket import *
from threading import Thread
import re #用正则表达式检索客户端的请求信息
def recvsocket(client_socket):
recvdata = client_socket.recv(1024)
print("request data:", recvdata)
recv_lines = recvdata.splitlines() #将客户端请求的信息根据空格分割开
# for line in recv_lines:
# print(line) #打不打印都没关系,打印可以看到详细的内容
request_start_line = recv_lines[0] #取第一行内容,是客户端的GET请求信息
file_name = re.match(r"w+ +(/[^ ]*) ",request_start_line.decode("utf-8")).group(1)
if "/" == file_name: #拿到请求的详细地址,如果是根目录,就将文件地址加上
file_name = "/index.html"
try:
file = open(HTML_ROOT_DIR + file_name,"rb") #打开文件
except IOError: #如果打不开,就返回文件不存在
response_start_line = "HTTP/1.1 404 Not Foudrn" #状态码
response_headers = "Server: pycharm serverrn" #响应头
response_boby = "The file is not fund!" #响应码
else:
file_data = file.read() #能打开,就读取
file.close() #关闭文件
response_start_line = "HTTP/1.1 200 OKrn"
response_headers = "Server: pycharm serverrn"
response_boby = file_data.decode("utf-8") #响应报头,内容就是刚才读取的html文件
response = response_start_line + response_headers + "rn" + response_boby
print("response data:", response)
client_socket.send(response.encode("utf-8"))
client_socket.close()
if __name__ == '__main__':
HTML_ROOT_DIR = "./html" #本地已经建好的html文件地址
server = socket(AF_INET, SOCK_STREAM)
server.bind(("", 7788))
server.listen(5)
while True:
client_socket , ip_port = server.accept()
print("%s:%s>>>正在连接中。。。"%ip_port)
childthread = Thread(target=recvsocket , args=(client_socket,))
childthread.start()
访问结果