1. TCP网络应用程序开发
TCP客户端程序是指运行在用户设备上的程序,主动发起连接请求的,是客户端程序。TCP服务端程序是指运行在服务器设备上的程序,专门为客户端提供数据服务,等待接受连接请求的是服务端程序。
网络连接助手充当的是与开发出来的程序进行数据交互的角色,开发TCP客户端时,网络连接助手充当服务端的角色,开发服务端时,网络连接助手充当客户端的角色。
1.1 TCP客户端开发
1.1.1 准备好服务端
这样服务端就开启了。
1.1.2 开发TCP客户端
TCP客户端开发的步骤:
- 创建客户端套接字
- 和服务端套接字建立连接
- 发送数据
- 接收数据
- 关闭客户端套接字
# tcp客户端
import socket
if __name__ == '__main__':
# 1. 创建客户端套接字
tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 2. 和服务端套接字连接 这一步,建立连接
tcp_client_socket.connect(("10.10.22.29",8080))
# 3.发送数据到服务端
# 转成二进制
send_data = "hello".encode("utf-8")
tcp_client_socket.send(send_data)
# 4. 从服务端接收数据 1024每次接收的最大字节数
recv_data = tcp_client_socket.recv(1024)
recv_data = recv_data.decode("utf-8")
print("接收到服务器发送过来的数据:",recv_data)
# 5. 关闭套接字
tcp_client_socket.close()
关键的第二步,建立连接,使用网络连接助手中的ip地址和端口号。
1.1.3 接收服务端发来的数据
上面的程序运行起来后,就和服务端建立起了连接,并且在等待接收服务端发过来的数据了。
选择对应的客户端,点击发送,客户端就可以接收到服务端发送过来的数据了。
1.2 TCP服务端的开发
1.2.1 准备好客户端
选择类型为客户端,远程主机地址填计算机的ip地址:
1.2.2 TCP服务端的开发
- 创建服务端套接字对象
- 绑定端口号
- 设置监听
- 等待客户端的连接请求
- 接收数据
- 发送数据
- 关闭套接字
#tcp 服务端的开发
import socket
if __name__ == '__main__':
# 1.创建服务端套接字对象 socket.AF_INET -- IPV4 socket.AF_INET6 -- IPV6
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 2.绑定端口号 让客户端和服务端建立连接
# 第一个参数表示ip地址,不用指定,表示本机的任何一个ip都行 第二个参数:端口号
tcp_server_socket.bind(("",9090))
# 3. 设置监听 128 表示最大等待建立连接的个数
tcp_server_socket.listen(128)
# 4. 等待客户端的连接请求 这个方法会阻塞
# 连接成功会返回一个新的套接字 和客户端通信使用新的套接字 收发数据等。
# tcp_server_socket只负责等待接收客户端的连接请求
new_client,ip_port = tcp_server_socket.accept()
# 5. 接收客户端数据
recv_data = new_client.recv(1024)
recv_data = recv_data.decode("gbk")
print("客户端传递过来的数据:",recv_data)
# 6. 发送数据到客户端
send_data = "问题正在解决中。。。"
send_data = send_data.encode("gbk")
new_client.send(send_data)
# 7. 关闭套接字
tcp_server_socket.close()
1.2.3 接收客户端传来的数据
1.3 多任务版TCP服务端程序
- 编写一个循环等待接收客户端的连接请求。
- 当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞。
- 把创建的子线程设置成为守护主线程,防止主线程无法退出
# 多任务版TCP服务端
import socket
import threading
# 处理客户端的请求
def handle_client_request(new_client_socket,ip_port):
# 循环接收客户端发送的数据
while True:
# 接收客户端发送的数据
recv_data = new_client_socket.recv(1024)
if recv_data:
print(recv_data.decode("gbk"),ip_port)
# 回复
new_client_socket.send("ok".encode("gbk"))
else:
print("客户端下线了...",ip_port)
break
# 关闭和客户端连接的套接字
new_client_socket.close()
if __name__ == '__main__':
# 1. 创建服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 2.设置端口号复用,让程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
# 3. 绑定端口号
tcp_server_socket.bind(("",9090))
# 4. 设置监听
tcp_server_socket.listen(128)
# 5. 循环等待接收客户端的连接请求
while True:
new_client_socket,ip_port = tcp_server_socket.accept()
print("客户端连接成功:",ip_port)
# 客户端连接成功后,创建一个子线程,不同子线程负责接收不同客户端的消息
sub_thread = threading.Thread(target=handle_client_request,args=(new_client_socket,ip_port))
# 设置守护主线程
sub_thread.setDaemon(True)
# 启动子线程
sub_thread.start()
可以循环接收客户端发过来的消息。
2. 静态Web服务器的开发
静态web服务器就是可以为发出请求的浏览器提供静态文档的程序。
2.1 使用python自带的静态web服务器
python -m http server 9000
9000是指定端口号,可以不写,不写默认8080
访问python自带的静态web服务器
在静态资源所在的目录中执行-m命令,静态web服务器运行后,在浏览器中访问
2.2 搭建自己的静态web服务器
2.2.1 搭建返回固定页面的web服务器
import socket
if __name__ == '__main__':
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置端口号复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
# 绑定端口号
tcp_server_socket.bind(("",9000))
# 设置监听
tcp_server_socket.listen(128)
while True:
new_socket,ip_port = tcp_server_socket.accept();
# 连接建立成功
recv_data = new_socket.recv(4096)
recv_data = recv_data.decode("utf-8")
print(recv_data)
with open("static/index.html","rb") as file:
file_data = file.read()
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Server:PWS11.0\r\n"
response_body = file_data
# 拼接响应报文
response_data = (response_line + response_header + "\r\n").encode("utf-8") +response_body
#发送数据
new_socket.send(response_data)
# 关闭服务器与客户端套接字
new_socket.close()
代码和前面的搭建TCP服务器差不多,不同的是with open("static/index.html","rb") as file: 这里需要去读取 文件,并拼接响应行、响应头、响应体之后,发送给客户端
服务端运行起来之后,使用浏览器访问
2.2.2 搭建返回指定页面的动态服务器
# 搭建返回指定页面的web服务器
import socket
def main():
# 创建服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_server_socket.bind(("", 9000))
tcp_server_socket.listen()
while True:
new_socket, ip_port = tcp_server_socket.accept()
recv_data = new_socket.recv(4096)
if len(recv_data) == 0:
print("关闭浏览器了")
new_socket.close()
return
recv_data = recv_data.decode("utf-8")
print(recv_data)
# 根据指定字符串进行分割,最大分割次数指定2
recv_data_list = recv_data.split(" ", maxsplit=2)
# 得到请求的路径
request_path = recv_data_list[1]
print(request_path)
# 如果没有指定路径,返回index.html
if request_path == "/":
request_path = "/index.html"
# 动态打开指定文件
try:
with open("static" + request_path, "rb") as file:
# 读取文件数据
file_data = file.read()
# 请求资源不存在 返回404页面
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Server:PWS11.0\r\n"
response_body = file_data
# 拼接响应报文
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送数据
new_socket.send(response_data)
except Exception as e:
# 请求资源不存在 返回404页面
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Server:PWS11.0\r\n"
with open("static/error.html", "rb") as file:
file_data = file.read()
# 响应体
response_body = file_data
# 拼接响应报文
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送数据
new_socket.send(response_data)
finally:
# 关闭服务器套接字
new_socket.close()
if __name__ == '__main__':
main()
这里要注意的是:获取的请求路径,需要spilt一下,获取到request_path,拼接到读取文件的路径里。 recv_data_list = recv_data.split(" ", maxsplit=2) # 得到请求的路径 request_path = recv_data_list[1]
recv_data_list = recv_data.split(" ", maxsplit=2)
# 得到请求的路径
request_path = recv_data_list[1]
使用浏览器请求:
2.2.3 多任务版静态web服务器
# 多任务版静态web服务器
import socket
import threading
# 处理客户端请求
def handle_client_request(new_socket):
recv_data = new_socket.recv(4096)
if len(recv_data) == 0:
print("关闭浏览器了")
new_socket.close()
return
recv_data = recv_data.decode("utf-8")
print(recv_data)
# 根据指定字符串进行分割,最大分割次数指定2
recv_data_list = recv_data.spit(" ",maxsplit = 2)
# 获取请求的资源路径
request_path = recv_data_list[1]
print(request_path)
if request_path == "/":
request_path = "/index.html"
try:
with open("static" + request_path,"rb") as file:
file_data = file.read()
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS1.0\r\n"
response_body = file_data
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
new_socket.send(response_data)
except Exception as e:
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS1.0\r\n"
with open("static/error.html","rb") as file:
file_data = file.read()
response_body = file_data
response_data = (response_line + response_header + "\r\n").encode("utf-8") +response_body
new_socket.send(response_data)
finally:
new_socket.close()
def main():
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置端口号复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_server_socket.bind(("",8000))
tcp_server_socket.listen(128)
while True:
new_socket,ip_port = tcp_server_socket.accept()
print(ip_port)
# 当客户端和服务器建立连接时,创建子线程 在子线程接收客户端的消息
sub_thread = threading.Thread(target=handle_client_request,args=(new_socket,))
# 设置守护主线程
sub_thread.setDaemon(True)
sub_thread.start()
if __name__ == '__main__':
main()
这里需要注意的就是,当客户端与服务器建立连接时,创建一个子线程,子线程去接收客户端的消息,并回复。
2.2.4 面向对象版本web服务器
# 面向对象
import socket
import threading
class HttpWebServer(object):
def __init__(self):
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_server_socket.bind(("", 8000))
tcp_server_socket.listen(128)
self.tcp_server_socket = tcp_server_socket
# 处理客户端请求
@staticmethod
def handle_client_request(new_socket):
recv_data = new_socket.recv(4096)
if len(recv_data) == 0:
print("关闭浏览器了")
new_socket.close()
return
recv_data = recv_data.decode("utf-8")
print(recv_data)
# 根据指定字符串进行分割,最大分割次数指定2
recv_data_list = recv_data.spit(" ", maxsplit=2)
# 获取请求的资源路径
request_path = recv_data_list[1]
print(request_path)
if request_path == "/":
request_path = "/index.html"
try:
with open("static" + request_path, "rb") as file:
file_data = file.read()
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS1.0\r\n"
response_body = file_data
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
new_socket.send(response_data)
except Exception as e:
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS1.0\r\n"
with open("static/error.html", "rb") as file:
file_data = file.read()
response_body = file_data
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
new_socket.send(response_data)
finally:
new_socket.close()
def start(self):
while True:
new_socket, ip_port = self.tcp_server_socket.accept()
print(ip_port)
# 当客户端和服务器建立连接时,创建子线程 在子线程接收客户端的消息
sub_thread = threading.Thread(target=self.handle_client_request, args=(new_socket,))
# 设置守护主线程
sub_thread.setDaemon(True)
sub_thread.start()
def main():
webServer = HttpWebServer()
webServer.start()
if __name__ == '__main__':
main()
3.编写处理获取动态资源的框架
动态的数据,是网页上每天都会改变的数据,这些数据是去找数据库拿的。
静态的资源找Web服务器获取,静态的资源是不会经常变化的资源,如png/css文件等,web服务器可以先把这些资源准备好。动态的资源找web框架获取,获取到之后web框架把资源返回给web服务器,web服务器再把响应结果发送给浏览器。
4.使用Django搭建服务端
4.1 Django环境搭建
使用python虚拟环境下载Django,首先在Windows上搭建python虚拟环境。具体参照下面的文档 blog.csdn.net/qq_52421092… blog.csdn.net/weixin_4598…
4.2 创建django项目
D:\pythonenve>django-admin startproject django1
相对应的目录下就创建了django1项目
D:\pythonenve>cd django1
D:\pythonenve\django1>python manage.py migrate
D:\pythonenve\django1>python manage.py runserver 运行开发服务器
D:\pythonenve\django1>python manage.py --help
任务启动起来之后,浏览器输入http://127.0.0.1:8000/ 如果出现:
说明搭建成功
退出:ctrl+c
下次进入虚拟环境还要再次激活,使用activate.bat命令激活 激活之后再使用命令
D:\pythonenve\django1>python manage.py runserver 运行开发服务器
运行服务器
创建子项目:
D:\pythonenve\django1>python manage.py startapp xxx
使用ide打开django项目
配置环境 打开setting选项
安装PyMySQL
pip install PyMySQL
使用pymysql