文章目录

  • 1. IP 地址
  • 2. 端口
    • 2.1 端口 介绍
    • 2.2 端口号 介绍
  • 3. TCP
    • 3.1 为什么要用TCP?
    • 3.2 TCP 和 UDP 的 解释
    • 3.3 TCP 步骤 和 特点
  • 4. socket(套接字)
  • 5. TCP 网络应用程序开发流程(重要)
    • 5.1 刚安装ubuntu20遇到的问题
    • 5.2 TCP 两个程序开发过程
    • 5.3 TCP 客户端开发程序
    • 5.3 TCP 服务端开发程序
  • 6. TCP 端口复用(释放端口)
  • 7. 在服务端中,如何判断客户端是否关闭?
  • 8. TCP服务端 单进程函数模式
  • 9. TCP服务端 多任务开发(多进程)
  • 10. http 协议
    • 10.1 HTTP 协议的介绍
    • 10.2 HTTP 协议的作用
    • 10.3 浏览器使用 HTTP 访问web服务器的 通信流程
  • 11. URL 统一资源定位符
  • 12. HTTP 请求报文
  • 13. HTTP 响应报文(应答报文)
  • 14. 静态web服务器
    • 14.1 静态web服务器 基本代码
    • 14.2 静态web服务器 传输文件(图片,html,css等等类型文件)
    • 14.3 静态web服务器 指定页面
    • 14.4 静态web服务器 使用try-catch来解决找不到路径。
    • 14.5 静态web服务器 函数版本
    • 14.6 静态web服务器 多任务
    • 14.7 静态web服务器 面向对象
    • 14.8 静态web服务器 终端启动
    • 14.9 静态web服务器 动态绑定端口

1. IP 地址


IP 地址就是标识网络中设备的一个地址。

在平时,我们直接百度IP地址,就可以查到我们当前所在的互联网外网地址。

咱们通过ifconfig或ipconfig来查看本机的网络配置时,经常看到192.168.xxx.xxx。
像192.168.xxx.xxx,这样是我们通过互联网拿到的内网(局域网)地址。


IPv4(inet)详解 :

  • IPv4的ip是由10进制数表示的。
  • 1个字节最大就是255,255的二进制位:1111 1111。
  • IPv4的IP是由4个字节组成的,因此IPv4是有限的,最大就是255。例如:255.255.255.1。
  • 127.0.0.1 指的是本机地址。

IPv6(inet6)详解:

  • IPv6的ip是由16进制数表示。
  • IPv6的数量远远大于IPv4,IPv4地址已经不够用了。据说,IPv6可能给地球每一粒沙子赋予ip也是够用的,可见它的数量多么庞大。

目前都是一个小区或者很多人都共用一个IP公网地址,这样也算是缓解了IPv4数量有限的问题,但因为好多人共用一个IP地址网络的速度肯定不是很快!!!


2. 端口

2.1 端口 介绍


通过网络IP,将数据传送到电脑中,但是传递给谁呢???
飞秋?QQ?还是微信?或者其他软件,游戏子类的?

为了解决这一问题,就用到了端口(端口号),每一个网络程序软件都会有一个端口,想要给对应的程序或软件发送数据,找到对应的端口即可。

端口是传输数据的通道,好比教师的门,是数据传输必经之路。

2.2 端口号 介绍


端口号:操作系统为了统一管理这么多端口,就对端口进行了编号,这就是端口号。

端口号有65536个。

并不是所有的程序都需要端口,例如闹钟,单机游戏等等不需要联网的程序软件。


端口号分类:(知名端口号,动态端口号)


3. TCP

TCP讲述的是C/S架构,客户端和服务端的通信过程。

3.1 为什么要用TCP?


网络应用程序之间的通信流程:

通过IP地址找到对应的设备,然后再通过端口号找到对应的端口,再通过端口把数据传输给应用程序。流程是这样的,但数据不能随便发送,在发送之前还需要选择一个对应的传输协议,保证程序之间按照指定的传输规则进行数据的通信,而这个传输协议就是TCP。

3.2 TCP 和 UDP 的 解释

TCP(Transmission Control Protocol)简称传输协议,它是一种面向连接,可靠的,基于字节流的传输层通信协议。TCP就是先确认(建立连接),然后传输数据。

UDP(User Datagram Protocol)简称用户数据报协议,是一种无连接不可靠传输的传输协议,它是广播式,数据我只管发送过去,能不能接受我不管,就像发短信一样。因此由于它的不可靠传输,就容易产生丢包或接受不到数据的情况。

3.3 TCP 步骤 和 特点


TCP通信步骤:

  1. 创建连接
  2. 传输数据
  3. 关闭连接

解释一下,TCP的流量控制和阻塞管理:

意思就是发送方和接收方的网络流畅不一样,发送方一下次发送1g,而接收方接受很慢远小于1g,这个时候TCP协议,就会设定发送方的流量控制和阻塞管理,从而达到双方一个流量平衡的状态。


解释一下,可靠传输和不可靠传输:

其实就是丢不丢包,信息是否完整,可靠传输不会丢包!像TCP采用发送应答机制,超时重传等等功能,就绝不会产生丢包的情况。UDP没有这些功能,它只管发送,其他都不管,因此算是不可靠传输。

像平时的下载文件(百度网盘,迅雷),QQ,微信,浏览器上网等都是必须要可靠传输,信息必须完整,因此这里都是TCP协议支撑。像直播类似的,都是UDP传输。

4. socket(套接字)


socket(简称 套接字) 是进程之间通信一个工具,就像生活中的插座,进程之间想要进行网络通信需要基于这个socket。

socket作用:负责进程之间的网络数据传输,好比数据的搬运工。

两个进程之间通过socket来传输数据:

5. TCP 网络应用程序开发流程(重要)

5.1 刚安装ubuntu20遇到的问题


  • mNetAssist 是linux系统中tcp调试工具(很重要)!!!

  • 在ubuntu20中安装时,是没有ssh服务,需要安装openssh-server服务。

  • root密码开始不知道,可以通过sudo passwd,修改root密码。

ubuntu20.04版本系统,安装桌面系统:

#!/bin/bash
#更新软件库
apt-get update
#升级软件
apt-get upgrade
#安装ubuntu桌面系统
apt-get install ubuntu-desktop

5.2 TCP 两个程序开发过程


TCP 网络应用程序开发分为:

  • TCP客户端程序开发
  • TCP服务端程序开发

TCP客户端和TCP服务端的程序开发流程:

recv英文就是receive接受。

5.3 TCP 客户端开发程序


开发TCP客户端程序开发步骤:

  1. 创建客户端套接字对象
  2. 和服务端套接字建立连接
  3. 发送数据
  4. 接受数据
  5. 关闭客户端套接字

编解码:( encode()和decode() )

  • 网络中必须传输二进制的数据。
  • 字符串转换为二进制 encode(“utf8”)。
  • 二进制转换成字符串decode(“utf8”)。

注意:utf-8编码的数据必须用utf-8解码!!


TCP客户端代码案例:

import socket# 1. 创建客户端套接字对象
# socket的参数:
# 参数1:ipv4(指定ip协议的版本) , 指定ip版本ipv4,ipv6等
# 参数2:选择协议(SOCK_STREAM指的就是tcp协议 , 指定协议tcp,udp等)
tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM);# 2. 和服务端套接字建立连接
# 参数:元组(有两个元素)
# 两个元素分别是 服务器端IP地址(字符串形式) 和 服务器的端口号(正常数字形式)。
tcp_client_socket.connect(("192.168.2.70",8080))# 3. 发送数据
# 发送数据的时候需要先转化为二进制形式,这就需要用到encode()方法定义。
# encode()方法默认为utf-8编码。
data = "123456"
tcp_client_socket.send(data.encode("utf8"))# 4. 接受数据
# 参数:以字节为单位的接受的数据大小(1024)
recv_data = tcp_client_socket.recv(1024)
print(recv_data.decode("utf8"))# 5. 关闭客户端套接字
tcp_client_socket.close()

5.3 TCP 服务端开发程序


开发TCP 服务端程序开发步骤:

  1. 创建服务端套接字对象。
  2. 绑定端口号。
  3. 设置监听。
  4. 等待接受客户端的连接请求。
  5. 接受数据。
  6. 发送数据。
  7. 关闭套接字。
import socket# 1. 创建服务端套接字对象。
# 参数是相同的
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)# 2. 绑定端口号。
# 参数:元组(两个元素)
# 两个元素,分别是服务器IP地址(字符串) ,端口号(数字形式)
# 不写默认是本机的ip地址("127.0.0.1"或"")
# bind()的作用就是绑定自己服务器的端口号。
tcp_server_socket.bind(("",8080))# 3. 设置监听。
# 参数:最大监听个数(就是排队处理的最大等待数量,如果在这个排队中排129超过了128个,就会报错。)
# 注意:经过了listen监听后,tcp_server_socket从主动套接字变成了被动套接字。
tcp_server_socket.listen(128)# 4. 等待接受客户端的连接请求,如果没有发过来请求就阻塞等待接受客户端请求。(打电话的客服人员一样,等待用户打过来电话)
# 返回值:是一个元组(也是有两个元素)
# 返回值元素 =》 元素1:和客户端进行通讯的socket。 元素2:客户端的地址信息(ip地址,端口号)
# 我们可以用拆包语法,将元组中的两个元素,赋予了 client_socket , client_addr 。
client_socket,client_addr = tcp_server_socket.accept()# 5. 接受数据。
# 参数一样,设置接受数据的大小(1个字节)
client_data = client_socket.recv(1024)
client_data = client_data.decode()# 对二进制的数据进行解码
print(client_data)# 6. 发送数据。
send_data = "123".encode()
client_socket.send(send_data)# 7. 关闭套接字。
client_socket.close() # 一定要先关闭这个socket变量服务
tcp_server_socket.close()

注意:代码中有两个socket变量,tcp_server_socket 和 client_socket ,它们两个在代码中的作用也不同。

6. TCP 端口复用(释放端口)


端口复用设置作用: 一旦服务端关闭,端口立马释放。

import sockettcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)# 端口复用设置:
# setsocketopt:设置socket选项
# 参数1:socket选项列表(SOL)
# 参数2:地址复用
# 参数3:True(开启选项),默认(False:不开启选项)
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
# 端口复用设置作用: 一旦服务端关闭,端口立马释放。tcp_server_socket.bind(("",8080))tcp_server_socket.listen(128)client_socket,client_addr = tcp_server_socket.accept()client_data = client_socket.recv(1024)
client_data = client_data.decode()
print(client_data)send_data = "123".encode()
client_socket.send(send_data)client_socket.close()
tcp_server_socket.close()

7. 在服务端中,如何判断客户端是否关闭?


import sockettcp_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(("",8080))tcp_server_socket.listen(128)client_socket,client_addr = tcp_server_socket.accept()# 如果客户端关闭,这里也相应的应该关闭才对
while True:# 如果客户端关闭,这里会接受到空数据,因此可以通过这个来判断客户端是否关闭。client_data = client_socket.recv(1024)# 通过判断长度为零,来确认是否关闭数据。if len(client_data) == 0:print("客户端关闭了!!!")break;client_data = client_data.decode()print(client_data)send_data = "123".encode()client_socket.send(send_data)client_socket.close()
tcp_server_socket.close()

8. TCP服务端 单进程函数模式


这里是一个主进程的TCP服务函数版本。

import socket# 该函数用来处理客户端请求函数
def handler_client_request(client_socket):# 如果客户端关闭,这里也相应的应该关闭才对while True:# 如果客户端关闭,这里会接受到空数据,因此可以通过这个来判断客户端是否关闭。client_data = client_socket.recv(1024)# 通过判断长度为零,来确认是否关闭数据。if len(client_data) == 0:print("客户端关闭了!!!")breakclient_data = client_data.decode()print(client_data)send_data = "123".encode()client_socket.send(send_data)client_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(("",8080))tcp_server_socket.listen(128)# 这个while目的是让服务器一直等待客户请求。while True:client_socket,client_addr = tcp_server_socket.accept()# 处理客户端的请求handler_client_request(client_socket)client_socket.close()tcp_server_socket.close()if __name__ == '__main__':main()

9. TCP服务端 多任务开发(多进程)


目前以上的操作都是单进程的操作,如果再开一个服务端就会等待,等第一个服务端资源释放后,再接受数据。

通过创建子进程,能够处理多个TCP客户端发送的数据。

import socket
import multiprocessing# 该函数用来处理客户端请求函数
def handler_client_request(client_socket):# 如果客户端关闭,这里也相应的应该关闭才对while True:# 如果客户端关闭,这里会接受到空数据,因此可以通过这个来判断客户端是否关闭。client_data = client_socket.recv(1024)# 通过判断长度为零,来确认是否关闭数据。if len(client_data) == 0:print("客户端关闭了!!!")breakclient_data = client_data.decode()print(client_data)send_data = "123".encode()client_socket.send(send_data)client_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(("",8080))tcp_server_socket.listen(128)# 这个while目的是让服务器一直等待客户请求。while True:client_socket,client_addr = tcp_server_socket.accept()# 通过创建子进程,能够处理多个TCP客户端发送的数据。# 创建一个子进程sub_process = multiprocessing.Process(target=handler_client_request,args=(client_socket,))# 开启子进程sub_process.start()client_socket.close()tcp_server_socket.close()if __name__ == '__main__':main()

socket不是将数据直接发送给网卡的,而是发送给缓冲区。

10. http 协议

http讲述的是B/S架构,浏览器和服务器之间的通信。

10.1 HTTP 协议的介绍


HTTP 协议全称为:HyperText Transfer Protocol,超文本传输协议。

超文本是超级文本的缩写,是指超越文本限制或者超链接,比如:图片,音乐,视频,超链接等等属于超文本。

传输HTTP协议格式的数据是基于TCP传输协议的,发送数据之前需要先建立连接。
也就是HTTP协议是一个基于TCP传输协议传输数据的。

10.2 HTTP 协议的作用


它规定了浏览器和Web服务器通信数据的格式,也就是说浏览器和web服务器通信需要使用http协议。

10.3 浏览器使用 HTTP 访问web服务器的 通信流程



平时我们访问像Facebook,谷歌商店这样的网站,没法访问,就是因为域名解析服务器被限制了,域名无法找到对应的ip地址,不让我们访问,因此才访问不到的。


https和http的区别:

  • https是一种安全的网络通信协议。
  • https就是对数据进行了加密而已(就因此才会安全)。

11. URL 统一资源定位符


URL的组成部分:

  • 第一部分:协议部分: https// , http:// , ftp://。
  • 第二部分:域名部分:例如:baidu.com 。
  • 第三部分:资源路径部分:服务器端的资源路径位置。

12. HTTP 请求报文


请求报文:给服务端发送的数据,就是请求报文。
应答报文:给浏览器端回复的数据,就是应答报文。


请求报文的两种格式:

  • get:只向服务器要数据,是不给服务器提供数据的。
  • post:会给服务器提供数据。

请求报文的组成:(从上到下的部分)

  • 请求行
  • 请求头
  • 空行
  • 请求体(get方式没有请求体)

请求行格式:

GET /index.html HTTP/1.1(HTTP版本一直都是1.1版本) \r\n

请求方式 请求资源路径 协议版本(中间一定要有空格!!) \r\n

\r\n(\r是将光标放到前面,\n是将光标放置到下一行,这样就变成了换行到下面的第一个位置,在linux中必须写\r\n,win版本\r就行。)


请求头格式:

key:value \r\n

请求头采用的是键值形式,来设置网页相关属性。


空格格式:

\r\n

空格没啥格式,就是空行。


请求体格式:

name age addr 想要给服务器传递的数据。


13. HTTP 响应报文(应答报文)


响应报文的组成:

  • 响应行
  • 响应头
  • 空行
  • 响应体

响应行格式:

HTTP/1.1 200 OK \r\n
HTTP协议版本 状态码 状态描述


响应头格式:

key:value \r\n
同样也是设置应答数据的相关属性。


空行格式:

\r\n


响应体格式:

(浏览器中有一张百度的图片, 这个图片一定是响应体传输给浏览器的)
html css js 图片视频 服务器发送给浏览器的数据


14. 静态web服务器

14.1 静态web服务器 基本代码


就是在原来tcp协议的基础上面,添加上请求头请求行请求体空行等操作。

import socket# 创建socket,对应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(("",8080))# 设置监听
tcp_server_socket.listen(128)while True:# 接受tcp链接请求client_socket,addr = tcp_server_socket.accept()# 接受数据recv_data = client_socket.recv(100000)if len(recv_data) == 0:print("客户端关闭!!!")break# 解码查看接受的数据内容print(recv_data.decode())# 响应行response_line = "HTTP/1.1 200 OK \r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体response_body = "aaa"# 响应数据resonse_data = response_line+response_header+response_rn+response_body# 发送数据,不要忘记编码client_socket.send(resonse_data.encode())client_socket.close()# 这里不是循环聊天,而是向浏览器发送数据,因此只需要发送一次就可以了

14.2 静态web服务器 传输文件(图片,html,css等等类型文件)


import socket# 创建socket,对应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(("",8080))# 设置监听
tcp_server_socket.listen(128)while True:# 接受tcp链接请求client_socket,addr = tcp_server_socket.accept()# 接受数据recv_data = client_socket.recv(1000000)if len(recv_data) == 0:print("客户端关闭!!!")break# 解码查看接受的数据内容print(recv_data.decode())# 打开资源文件,   rb是read和二进制,二进制读取# open中,可以添加html文件,css文件等等一系列。f = open("D:/壁纸/3.jpg","rb")# 存放了图片资源file_data = f.read()f.close()# 响应行response_line = "HTTP/1.1 200 OK \r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = file_data# 响应数据 , 因为字符串和二进制不能相加的,所以将响应头响应行等都转换为二进制形式,在组合。resonse_data = (response_line+response_header+response_rn).encode()+response_body# 发送数据  因为上面转换了二进制,所以这里不需要在进行encode编码了client_socket.send(resonse_data)client_socket.close()# 这里不是循环聊天,而是向浏览器发送数据,因此只需要发送一次就可以了

14.3 静态web服务器 指定页面


实质上就是对请求报文体进行切割,将路径提取出来,访问对应的页面。

import socket# 创建socket,对应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(("",8080))# 设置监听
tcp_server_socket.listen(128)while True:# 接受tcp链接请求client_socket,addr = tcp_server_socket.accept()# 接受数据recv_data = client_socket.recv(1000000)if len(recv_data) == 0:print("客户端关闭!!!")break# 解码查看接受的数据内容recv_data = recv_data.decode()print("请求报文:",recv_data)# 对请求报文进行切割path_list = recv_data.split(" ")print("列表:",path_list)# 请求资源路径,实质上就是将路径从请求报文中提取出来,在open中打开而已request_path = path_list[1]# 打开资源文件,   rb是read和二进制,二进制读取f = open("./static"+request_path,"rb")# 存放了图片资源file_data = f.read()f.close()# 响应行response_line = "HTTP/1.1 200 OK \r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = file_data# 响应数据 , 因为字符串和二进制不能相加的,所以将响应头响应行等都转换为二进制形式,在组合。resonse_data = (response_line+response_header+response_rn).encode()+response_body# 发送数据  因为上面转换了二进制,所以这里不需要在进行encode编码了client_socket.send(resonse_data)client_socket.close()# 这里不是循环聊天,而是向浏览器发送数据,因此只需要发送一次就可以了

14.4 静态web服务器 使用try-catch来解决找不到路径。


使用try-catch来判断文件路径是否存在,从而告知浏览器端。

import socket# 创建socket,对应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(("",8080))# 设置监听
tcp_server_socket.listen(128)while True:# 接受tcp链接请求client_socket,addr = tcp_server_socket.accept()# 接受数据recv_data = client_socket.recv(1000000)if len(recv_data) == 0:print("客户端关闭!!!")break# 解码查看接受的数据内容recv_data = recv_data.decode()print("请求报文:", recv_data)# 对请求报文进行切割path_list = recv_data.split(" ")print("列表:", path_list)# 请求资源路径,实质上就是将路径从请求报文中提取出来,在open中打开而已request_path = path_list[1]# 异常捕获(防止出现异常的时候,服务器直接崩溃)try:# 打开资源文件,   rb是read和二进制,二进制读取f = open("./static" + request_path, "rb")# 存放了图片资源file_data = f.read()f.close()except Exception as e:# 证明:文件不存在print("异常问题",e)# 既然不存在就返回404# 响应行response_line = "HTTP/1.1 404 NOT FOUND\r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = "404,not found i am sorry!!!"resonse_data = response_line + response_header + response_rn+ response_bodyclient_socket.send(resonse_data.encode())else:# 响应行response_line = "HTTP/1.1 200 OK \r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = file_data# 响应数据 , 因为字符串和二进制不能相加的,所以将响应头响应行等都转换为二进制形式,在组合。resonse_data = (response_line+response_header+response_rn).encode()+response_body# 发送数据  因为上面转换了二进制,所以这里不需要在进行encode编码了client_socket.send(resonse_data)finally:client_socket.close()# 这里不是循环聊天,而是向浏览器发送数据,因此只需要发送一次就可以了

14.5 静态web服务器 函数版本


import socketdef handler_client_request(client_socket):"""和浏览器处理浏览器请求的函数"""# 接受数据recv_data = client_socket.recv(1000000)if len(recv_data) == 0:print("客户端关闭!!!")return# 解码查看接受的数据内容recv_data = recv_data.decode()print("请求报文:", recv_data)# 对请求报文进行切割path_list = recv_data.split(" ")print("列表:", path_list)# 请求资源路径,实质上就是将路径从请求报文中提取出来,在open中打开而已request_path = path_list[1]# 异常捕获(防止出现异常的时候,服务器直接崩溃)try:# 打开资源文件,   rb是read和二进制,二进制读取f = open("./static" + request_path, "rb")# 存放了图片资源file_data = f.read()f.close()except Exception as e:# 证明:文件不存在print("异常问题", e)# 既然不存在就返回404# 响应行response_line = "HTTP/1.1 404 NOT FOUND\r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = "404,not found i am sorry!!!"resonse_data = response_line + response_header + response_rn + response_bodyclient_socket.send(resonse_data.encode())else:# 响应行response_line = "HTTP/1.1 200 OK \r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = file_data# 响应数据 , 因为字符串和二进制不能相加的,所以将响应头响应行等都转换为二进制形式,在组合。resonse_data = (response_line + response_header + response_rn).encode() + response_body# 发送数据  因为上面转换了二进制,所以这里不需要在进行encode编码了client_socket.send(resonse_data)finally:client_socket.close()def main():"""控制整个服务器流程的函数tcp_server_socket: 用来接受连接的socketclient_socket: 用来处理和浏览器之间的数据交流的socket"""# 创建socket,对应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(("",8080))# 设置监听tcp_server_socket.listen(128)while True:# 接受tcp链接请求client_socket,addr = tcp_server_socket.accept()# 调用处理浏览器请求的函数handler_client_requesthandler_client_request(client_socket)if __name__ == '__main__':main()

14.6 静态web服务器 多任务



如果向上面这样,多个任务访问时就会卡死,因为是单进程,因此我们要创建多进程来操作。

我们通过使用多进程,来解决多个任务访问我们服务器。

import socket
import multiprocessing
import timedef handler_client_request(client_socket):"""和浏览器处理浏览器请求的函数"""# 接受数据recv_data = client_socket.recv(1000000)if len(recv_data) == 0:print("客户端关闭!!!")return# 解码查看接受的数据内容recv_data = recv_data.decode()print("请求报文:", recv_data)# 对请求报文进行切割path_list = recv_data.split(" ")print("列表:", path_list)# 请求资源路径,实质上就是将路径从请求报文中提取出来,在open中打开而已request_path = path_list[1]# 异常捕获(防止出现异常的时候,服务器直接崩溃)try:# 打开资源文件,   rb是read和二进制,二进制读取f = open("./static" + request_path, "rb")# 存放了图片资源file_data = f.read()f.close()except Exception as e:# 证明:文件不存在print("异常问题", e)# 既然不存在就返回404# 响应行response_line = "HTTP/1.1 404 NOT FOUND\r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = "404,not found i am sorry!!!"resonse_data = response_line + response_header + response_rn + response_bodyclient_socket.send(resonse_data.encode())time.sleep(60)client_socket.close()else:# 响应行response_line = "HTTP/1.1 200 OK \r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = file_data# 响应数据 , 因为字符串和二进制不能相加的,所以将响应头响应行等都转换为二进制形式,在组合。resonse_data = (response_line + response_header + response_rn).encode() + response_body# 发送数据  因为上面转换了二进制,所以这里不需要在进行encode编码了client_socket.send(resonse_data)# 设置一个time来延缓关闭,这样浏览器端就会一直转圈time.sleep(60)client_socket.close()def main():"""控制整个服务器流程的函数tcp_server_socket: 用来接受连接的socketclient_socket: 用来处理和浏览器之间的数据交流的socket"""# 创建socket,对应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(("",8080))# 设置监听tcp_server_socket.listen(128)while True:# 接受tcp链接请求client_socket,addr = tcp_server_socket.accept()# 创建多进程sub_process = multiprocessing.Process(target=handler_client_request,args=(client_socket,))sub_process.start()print(sub_process)if __name__ == '__main__':main()

14.7 静态web服务器 面向对象

面向对象就是通过使用class类来表现服务器启动等等。

import socket
import multiprocessingclass WebServer:def __init__(self):# 创建socket,对应tcp流式协议self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 端口复用self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 绑定地址和端口self.tcp_server_socket.bind(("", 8080))# 设置监听self.tcp_server_socket.listen(128)@staticmethoddef handler_client_request(client_socket):# 接受数据recv_data = client_socket.recv(1000000)if len(recv_data) == 0:print("客户端关闭!!!")return# 解码查看接受的数据内容recv_data = recv_data.decode()print("请求报文:", recv_data)# 对请求报文进行切割path_list = recv_data.split(" ")print("列表:", path_list)# 请求资源路径,实质上就是将路径从请求报文中提取出来,在open中打开而已request_path = path_list[1]# 异常捕获(防止出现异常的时候,服务器直接崩溃)try:# 打开资源文件,   rb是read和二进制,二进制读取f = open("./static" + request_path, "rb")# 存放了图片资源file_data = f.read()f.close()except Exception as e:# 证明:文件不存在print("异常问题", e)# 既然不存在就返回404# 响应行response_line = "HTTP/1.1 404 NOT FOUND\r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = "404,not found i am sorry!!!"resonse_data = response_line + response_header + response_rn + response_bodyclient_socket.send(resonse_data.encode())client_socket.close()else:# 响应行response_line = "HTTP/1.1 200 OK \r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = file_data# 响应数据 , 因为字符串和二进制不能相加的,所以将响应头响应行等都转换为二进制形式,在组合。resonse_data = (response_line + response_header + response_rn).encode() + response_body# 发送数据  因为上面转换了二进制,所以这里不需要在进行encode编码了client_socket.send(resonse_data)client_socket.close()def start(self):while True:# 接受tcp链接请求client_socket,addr = self.tcp_server_socket.accept()# 创建多进程sub_process = multiprocessing.Process(target=self.handler_client_request,args=(client_socket,))sub_process.start()print(sub_process)if __name__ == '__main__':web_server = WebServer()web_server.start()

14.8 静态web服务器 终端启动

将文件上传到我的云服务器端。

直接远程服务器python3 xxx.py 运行就可以了。

14.9 静态web服务器 动态绑定端口


注意:一般的云服务端口都要配置安全规则,想要测试一定要开发端口号。

import socket
import multiprocessing
import sysclass WebServer:# port默认可以设置为8080def __init__(self,port1=8080):# 创建socket,对应tcp流式协议self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 端口复用self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 绑定地址和端口self.tcp_server_socket.bind(("", int(port1)))# 设置监听self.tcp_server_socket.listen(128)@staticmethoddef handler_client_request(client_socket):# 接受数据recv_data = client_socket.recv(1000000)if len(recv_data) == 0:print("客户端关闭!!!")return# 解码查看接受的数据内容recv_data = recv_data.decode()print("请求报文:", recv_data)# 对请求报文进行切割path_list = recv_data.split(" ")print("列表:", path_list)# 请求资源路径,实质上就是将路径从请求报文中提取出来,在open中打开而已request_path = path_list[1]# 异常捕获(防止出现异常的时候,服务器直接崩溃)try:# 打开资源文件,   rb是read和二进制,二进制读取f = open("./static" + request_path, "rb")# 存放了图片资源file_data = f.read()f.close()except Exception as e:# 证明:文件不存在print("异常问题", e)# 既然不存在就返回404# 响应行response_line = "HTTP/1.1 404 NOT FOUND\r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = "404,not found i am sorry!!!"resonse_data = response_line + response_header + response_rn + response_bodyclient_socket.send(resonse_data.encode())client_socket.close()else:# 响应行response_line = "HTTP/1.1 200 OK \r\n"# 响应头response_header = "server:py1.0\r\n"# 空行response_rn = "\r\n"# 响应体, 此时这里file_data是二进制形式response_body = file_data# 响应数据 , 因为字符串和二进制不能相加的,所以将响应头响应行等都转换为二进制形式,在组合。resonse_data = (response_line + response_header + response_rn).encode() + response_body# 发送数据  因为上面转换了二进制,所以这里不需要在进行encode编码了client_socket.send(resonse_data)client_socket.close()def start(self):while True:# 接受tcp链接请求client_socket,addr = self.tcp_server_socket.accept()# 创建多进程sub_process = multiprocessing.Process(target=self.handler_client_request,args=(client_socket,))sub_process.start()print(sub_process)if __name__ == '__main__':# 获取动态端口if len(sys.argv) != 2:print("正确的格式是 python3 文件名 端口号 ")else:# print(sys.argv), 通过sys.argv来获得终端定义的端口 ,# 注意的是argv[x]里面的内容,都是str字符串类型的,因此可能涉及转换类型的问题,要注意!port = sys.argv[1]port1 = int(port)web_server = WebServer(port1)web_server.start()# 在终端运行python3 静态web服务器-动态绑定端口 9090
# 让服务者自定义端口号,例如9090

史上最全的python的web开发和网络编程【附属详细解释+案例】相关推荐

  1. python 完全面向对象_史上最全的Python面向对象知识点疏理

    原标题:史上最全的Python面向对象知识点疏理 面向对象技术简介 类: 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例.class 类变量:类变 ...

  2. 玩转Python必备:史上最全的Python库,【值得收藏,事半功倍】

    库名称     简介 Chardet字符编码探测器,可以自动检测文本.网页.xml的编码. colorama主要用来给文本添加各种颜色,并且非常简单易用. Prettytable主要用于在终端或浏览器 ...

  3. 这可能是史上最全的Python算法集!

    来源 | CSDN(ID:CSDNnews ) 本文是一些机器人算法(特别是自动导航算法)的Python代码合集. 其主要特点有以下三点:选择了在实践中广泛应用的算法:依赖最少:容易阅读,容易理解每个 ...

  4. python优化算法工具包_这可能是史上最全的 Python 算法集(建议收藏)

    原标题:这可能是史上最全的 Python 算法集(建议收藏) 导读:本文是一些机器人算法(特别是自动导航算法)的Python代码合集.其主要特点有以下三点: 选择了在实践中广泛应用的算法: 依赖最少: ...

  5. python bool 转vc int_史上最全的 Python 3 类型转换指南

    史上最全的 Python 3 类型转换指南-1.jpg (13.76 KB, 下载次数: 0) 2018-8-21 17:35 上传 int 支持转换为 int 类型的,仅有 float.str.by ...

  6. python算法动画_这可能是史上最全的Python算法集!

    来源 | CSDN(ID:CSDNnews ) 本文是一些机器人算法(特别是自动导航算法)的Python代码合集. 其主要特点有以下三点:选择了在实践中广泛应用的算法:依赖最少:容易阅读,容易理解每个 ...

  7. 史上最全面的python学生管理系统教程(二)

    目录 序言 sqlite使用教程 python sqlite使用教程 数据库构造 学生信息表结构: 教师信息表结构: 课程成绩表结构: 教师添加课程: 学生表连接课程成绩表: 数据库语句了解 sqli ...

  8. python高分书籍推荐_史上最全的Python书排行榜|你想知道的都在这里

    原标题:史上最全的Python书排行榜|你想知道的都在这里 感谢关注天善智能,走好数据之路↑↑↑ 欢迎关注天善智能,我们是专注于商业智能BI,大数据,数据分析领域的垂直社区,学习,问答.求职一站式搞定 ...

  9. 标星 2.7w+ 堪称史上最全的微信小程序开发资源汇总

    [公众号回复 "1024",免费领取程序员赚钱实操经验] 2017 年 1 月,微信小程序一夜成名. 微信小程序成名后,各大厂开始效仿,相继出现了支付宝.百度.今日头条.QQ.抖音 ...

最新文章

  1. centos7.2安装mysql 1
  2. 空调自控系统基础知识及应用
  3. 在oracle下我们如何正确的执行数据库恢复
  4. JavaScript学习随记——数组一
  5. mybatis配置insert/update/delete同一个模板
  6. 电影AI修复,让重温经典有了新的可能
  7. django xadmin 默认密码_Django的认证系统
  8. java 正负随机_如何产生一个随机的[0, n)范围内的Short值
  9. python 环境准备_virtualenvwrapper
  10. 为了进大厂,韩顺平Java教程百度云
  11. Mac 终端命令自动补齐的办法
  12. EC风扇电机如何工作?
  13. 怎么在微云服务器找一个文件,微云文件在哪里打开_怎么快速找到微云文件
  14. Windows 10家庭版也能共享打印机(中)解除Guest账户网络登录限制,实现局域网共享
  15. pandox怎么用_神器Pandoc的安装与使用 | Flyaway's Blog
  16. 通过canvas画出爱心图案,表达你的爱意!
  17. 一个mybatis动态 SQL查询的完整小案例。包含多表联合查询。
  18. SpringSecurity(安全)
  19. mysql 计算近30天总金额_计算月嫂每天工资,应该用总工资除以30天还是26天?-免费法律咨询...
  20. 计算机入门知识(如何使用操作系统)

热门文章

  1. SE2431L-R射频放大器
  2. Android实现button一边圆角一边直角
  3. 工作中对数据分析思路的一点思考
  4. OpenCV4.x图像处理实例-自动包围曝光(Auto Exposure Bracketing,AEB)
  5. 酒桌上的潜规则,男人必学,女人必知
  6. 【UE4 第一人称射击游戏】22-拾取弹药
  7. 汽车保养技巧 十大汽车保养技巧
  8. Tcl异常处理命令之try、throw
  9. 记一个rabbitmq启动失败解决方案
  10. Java多线程学习笔记(三)休眠(sleep),让步(yield),插队(join)