1. 静态web的创建
'''
编写一个TCP程序
获取浏览器发送的http请求报文数据
读取浏览器请求的页面数据化,把页面组装成HTTP响应报文数据发送给浏览器
HTTP响应报文数据发送完成后,关闭服务于客户端的套接字。
'''
import socket
def main():
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.bind(('192.168.1.100', 9000))
tcp_server_socket.listen(128)
while True:
new_socket, new_addr = tcp_server_socket.accept()
recv_client_data = new_socket.recv(4096) # 接收浏览器发送的请求
recv_client_content = recv_client_data.decode('utf-8') # 解码
# print(recv_client_content) # 打印请求报文
request_list = recv_client_content.split(" ")
# 请求资源路径
request_path = request_list[1]
with open('static' + request_path, 'r') as f:
file_data = f.read()
reponse_line = "HTTP/1.1 200 OK\r\n"
reponse_header = "Server: PWS1.0\r\n"
reponse_body = file_data
reponse_data = reponse_line + reponse_header + '\r\n' + reponse_body
new_socket.send(reponse_data.encode('utf-8'))
if __name__ == '__main__':
main()
用户输入需要的连接,返回对应的数据。
但是在Pycharm中返回的数据有错误,主要原因是缺少favicon.ico图标文件。
所以在static文件中添加一个favicon.ico文件
- 解决用户输入的地址我机没有时提供一个404没有找到的。
import socket
def main():
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.bind(('192.168.1.103', 9000))
tcp_server_socket.listen(128)
while True:
new_socket, new_addr = tcp_server_socket.accept()
recv_client_data = new_socket.recv(4096)
if len(recv_client_data) == 0:
new_socket.close()
continue
recv_client_content = recv_client_data.decode('utf-8')
print(recv_client_content)
request_list = recv_client_content.split(" ")
request_path = request_list[1]
try:
with open('static' + request_path, 'r', encoding='utf-8') as f:
file_data = f.read()
except Exception as e:
reponse_line = "HTTP/1.1 404 Not Found\r\n"
reponse_header = "Server: PWS1.0\r\n"
with open('static/404.html', 'r', encoding='utf-8') as f:
file_data = f.read()
reponse_body = file_data
reponse_data = reponse_line + reponse_header + '\r\n' + reponse_body
new_socket.send(reponse_data.encode('utf-8'))
else:
reponse_line = "HTTP/1.1 200 OK\r\n"
reponse_header = "Server: PWS1.0\r\n"
reponse_body = file_data
reponse_data = reponse_line + reponse_header + '\r\n' + reponse_body
new_socket.send(reponse_data.encode('utf-8'))
finally:
new_socket.close()
if __name__ == '__main__':
main()
解决当用户输入的错误的网址时,显示404网站。
2. 线程
多任务
-
概念:同时运行多个程序(任务)。
-
理解:
- **并发:**CPU 小于当前执行的任务。是假的多任务
- **并行:**CPU 大于当前执行的任务。是真的多任务
实现多任务的三种方式
- 线程
- 进程
- 协程
# threading.Thread 模块的理解
def __init__(self, group=None, target=None, name=None,
args=(), kwargs=None, *, daemon=None):
"""
This constructor should always be called with keyword arguments. Arguments are:
*group* should be None; reserved for future extension when a ThreadGroup
class is implemented.
*target* is the callable object to be invoked by the run()
method. Defaults to None, meaning nothing is called.
*name* is the thread name. By default, a unique name is constructed of
the form "Thread-N" where N is a small decimal number.
*args* is the argument tuple for the target invocation. Defaults to ().
*kwargs* is a dictionary of keyword arguments for the target
invocation. Defaults to {}.
If a subclass overrides the constructor, it must make sure to invoke
the base class constructor (Thread.__init__()) before doing anything
else to the thread.
"""
import threading
import time
def demo(): # 子线程
print('Demo...')
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
# 创建线程
t = threading.Thread(target=demo)
# 启动线程
t.start() # 主线程:等到子线程执行结束之后才会结束
防护线程
-
守护线程,也就是说不会等子线程结束。
-
使用方法: t.setDaemon(True)。
-
跳过 time.sleep(1) 时间。
import threading
import time
def demo():
print('Demo...')
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
t = threading.Thread(target=demo)
t.setDaemon(True)
# 守护线程,不会等子程序结束
t.start()
-
那是否可以实现子线程结束完毕,主线程才继续执行呢?
-
使用方法:t.join()
import threading
import time
def demo():
print('Demo...')
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
t = threading.Thread(target=demo)
t.join()
t.start()
-
raise RuntimeError(“cannot join thread before it is started”)
RuntimeError: cannot join thread before it is started在开始之前不能连接
import threading
import time
def demo():
print('Demo...')
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
t = threading.Thread(target=demo)
t.start()
t.join()
- 效果和直接用循环相同
'''同时运行'''
import threading
import time
def singe():
for i in range(5):
print('Singing...')
time.sleep(1)
def dance():
for i in range(5):
print('Dancing...')
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=singe)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
- run()方法 和普通调用的方法相同。
import threading
import time
def singe():
for i in range(5):
print('Singing...')
time.sleep(1)
def dance():
for i in range(5):
print('Dancing...')
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=singe)
t2 = threading.Thread(target=dance)
t1.run()
t2.run()
- 其他功能
1.查看线程的id
import threading
import time
def demo():
print('Demo...')
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
t = threading.Thread(target=demo)
t.start()
print(t.ident)
2.判断线程是否在活跃中
import threading
import time
def demo():
print('Demo...')
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
t = threading.Thread(target=demo)
t.start()
print(t.is_alive())
3. 查看线程数
- 查看线程数量使用
**threading.enumerate()**来查看当前线程的数量。
import threading
import time
def singe():
for i in range(5):
print('Singing...')
time.sleep(1)
def dance():
for i in range(5):
print('Dancing...')
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=singe)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
print(threading.enumerate())
查看线程是如何创建出来的
import threading
import time
def singe():
for i in range(3):
print('Singing...')
time.sleep(1)
def dance():
for i in range(6):
print('Dancing...')
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=singe)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
# 获取当前所有线程
while True:
print(threading.enumerate())
if len(threading.enumerate()) <= 1:
break
time.sleep(1)
当你去除延时的时候,你会发现结果会变得随机。
import threading
import time
def singe():
for i in range(5):
print('Singing...')
# time.sleep(1)
def dance():
for i in range(5):
print('Dancing...')
# time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=singe)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
# 获取当前所有线程
print(threading.enumerate())
原因:线程是毫无顺序的,谁先抢到资源谁就先运行,所以要加上延时来解决此问题。
4. 验证子线程的执行和创建
import threading
import time
def demo():
for i in range(3):
print('Demo...')
time.sleep(1)
if __name__ == '__main__':
print(threading.enumerate())
t = threading.Thread(target=demo)
print(threading.enumerate())
t.start()
print(threading.enumerate())
- 证明只有在start的时候子线程才被创建。
5. 继承threading .Thread
import threading
import time
class MyThread(threading.Thread):
def __init__(self, name):
super(MyThread, self).__init__(name=name)
# target指定的函数
def run(self):
for i in range(5):
print(i)
if __name__ == '__main__':
# 等于 threading.Thread()
mt = MyThread('threading')
mt.start()