python网络编程
第一部分
1.简述OSI7层模型及其作用?
# OSI7层模型
应用层 HTTP,HTTPS,FTP
表示层
会话层
传输层 封装端口 TCP/UDP协议
网络层 封装IP,ipv4,ipv6
数据链路层 封装mac地址,通过arp协议
物理层 转换成二进制字节流,封装成数据包,加上各种请求头,通过网络进行传输数据
2.简述TCP三次握手、四次挥手的流程。
三次握手是TCP协议建立连接的过程
假设,客户端想要连接服务端,首先客户端发给服务端一个syn请求,意思就是我客户端想要和服务端建立连接,然后服务端发送给客户端一个ack请求,意思就是可以和你建立连接,同时也发送一个syn请求,意思就是我和你客户端建立连接,TCP的数据传输需要两端都同意建立连接,所以TCP协议很安全,客户端收到syn请求,回给服务器一个syn随机数+n,和一个ack请求,意思就是我客户端同意了
四次挥手是TCP协议断开连接的过程
FIN
ACK
FIN
ACK
SYN 请求创建连接
FIN 请求断开连接
ACK 确认响应
3.TCP和UDP的区别?
TCP协议 可靠、面向连接、速度慢、能传输的数据长度不限
UDP协议 即时通讯工具,不可靠 面上数据包 速度快 能传输的数据长度有限
TCP协议 面向连接,传输速度慢,数据安全,传输的数据没有限制
UDP协议 面向数据包,传输速度块,数据可能丢包,传输的数据有限制
4.什么是黏包?
由于TCP协议传输数据是通过数据流传输的,数据和数据之间没有边界,如果发送端处理过快,或者接收端接收数据慢,都会造成数据包的黏包
5.什么是B/S和C/S架构?
B/S浏览器对服务器架构,节省资源,不用更新,不依赖环境
C/S客户端对服务器架构,安全性高,程序庞大
6.请实现一个简单的socket编程(客户端和服务端可以进行收发信息)
# 基于TCP协议的socket
# Server
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8000))
sk.listen()
conn,addr = sk.accept()
msg = conn.recv(1024).decode('utf-8')
print(msg)
conn.close()
sk.close()
# Client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8000))
msg = input('请输入信息:')
sk.send(msg.encode('utf-8'))
# 支持TCP的并发服务
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
conn = self.request
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1',9005),MyServer)
server.serve_forever()
# 基于UDP协议的socket
# server
improt socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',8000))
msg,cli_addr = sk.recvfrom(1024)
print(msg.decode('utf-8'))
# client stuff
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
ser_addr = ('127.0.0.1',8000)
sk.sendto(b'request', ser_addr)
7.简述进程、线程、协程的区别?
进程是操作系统分配资源的最小单位,一个进程中可以有多个线程
线程是操作系统调度的最小单位,同一个进程中的线程共享进程中的资源,只能并发,不能并行
协程也被称为微线程,实现单线程在多任务之间的自由切换,是线程执行任务的一种方式
8.什么是GIL锁?
GIL锁是python解释器中特有的锁
作用是每一个进程同一时刻,只能有一个线程被调用
9.进程之间如何进行通信?
IPC通信
1.管道Pipe(进程和进程之间只能单向通信)
2.Queue进程和进程之间可以双向通信
3.基于文件
10.python如何使用线程池、进程池?
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
p = ProcessPoolExecutor()
p = TheadPoolExecutor
res = p.submit(func,参数1,参数2)
res_new = res.result()
p.shutdown()
11.请通过yield关键词实现一个协程?
# 创建生成器
1.生成器表达式,(i for i in range(10))
2.生成器函数 函数中含有yield,需要初始化才能使用
def producer():
for i in range(100):
n = yield i
print('结果是%s',n)
def consumer():
g = producer()
g.send(None)
fo i in range(10):
res = g.send(i)
print(res)
customer()
12.什么是异步非阻塞?
同步:从上到下按照顺序依次执行
异步:不需等待异步的代码执行完毕,直接向下依次执行,自己又开启了一个线程,独自执行
异步非阻塞就是代码一旦遇到阻塞代码,就把阻塞代码异步
13.什么是死锁?如何避免?
互斥锁,死锁,递归锁
只上锁不解锁就是死锁
避免交叉使用锁,如果必须要使用,那就都是交叉使用的锁是同一个锁
14.程序从flag a执行到flag b的时间大致是多少秒?
import threading
import time
def _wait():
time.sleep(60)
# flag a
t = threading.Thread(target=_wait)
t.setDeamon(False)
t.start()
# flag b
0.0001
15.程序从flag a 执行到flag b的时间大致是多少秒?
improt threading
improt time
def _wait():
time.sleep(60)
# flag a
t = theading.Thread(target=_wait)
t.setDeamon(True)
t.start()
# flag b
0.01
16.程序从flag a执行到flag b的时间大致是多少秒?
import theading
import time
def _wait():
time.sleep(60)
# flag a
t = theading.Thread(target=_wait)
t.start()
t.join()
# flag b
60
17.读程序,请确认执行到最后number是否一定为0
import threaing
loop = int(1E7)
def _add(loop:int =1):
global number
for _ in range(loop):
number += 1
def _sub(loop:int=1):
global number
for _ in range(loop):
number-=1
number = 0
ta = theading.Thread(target=_add,args=(loop,))
ts = theading.Thread(target=_sub,args=(loop,))
ta.start()
ta.join()
ts.start()
ts.join()
一定为0
18.读程序,请确认执行到最后number是否一定为0
import threaing
loop = int(1E7)
def _add(loop:int =1):
global number
for _ in range(loop):
number += 1
def _sub(loop:int=1):
global number
for _ in range(loop):
number-=1
number = 0
ta = theading.Thread(target=_add,args=(loop,))
ts = theading.Thread(target=_sub,args=(loop,))
ta.start()
ts.start()
ta.join()
ts.join()
# 不一定为0
19.Mysql常见数据库引擎及区别?
innodb
menmory
myisam
blackhole
20.简述事务及其特性?
事务就是一个程序执行单元
一致性
原子性 事务中的所有sql语句,要么一起成功,要么事务并回滚
隔离性 事务和事务之间的过程是相互隔离的,并且有锁的机制,就是说当一条数据被一个事务操作时,其他需要操作本数据的事务需要等待
持久性 把数据写在硬盘上,数据的持久化存储
21.事务的隔离级别
读未提交
读已提交
可重复读
可序列化
22.char和varchar的区别?
char 定长,速度快
varchar 变长,速度慢,节省空间(数据的头部,会有1-2个字符存储数据长度)
23.mysql中varchar与char的区别以及varchar(50)中的50代表的含义
varchar(50)代表最多存储50个字符
24.Mysql中delete和truncate的区别
delete 删除数据
truncate 重置表(删除数据,重置自增ID)
25.where子句中有a,b,c三个查询条件,创建一个组合索引abc(a,b,c),以下哪种会命中索引
(a) 命中
(b) 不行
(c) 不行
(a,b) 命中
(b,c) 不行
(a,c) 命中
(a,b,c) 命中
26.组合索引遵循什么原则才能命中索引?
最左前缀原则,条件不能使用范围,可以使用and
where a >1 and b =1 and c = 100 不能命中
where b =1 and c = 100 or a = 10 不能命中
27.列举mysql常见的函数
count
avg
concat
concat_ws
sum
min
max
user
now
databases
28.Mysql数据库导入、导出的命令有哪些
# 数据库的导出(退出数据库,才能导出数据库)
mysqldump -uroot -p密码 db1.tab1 > db1.tab1.sql
# 数据库的导入(进入到mysql,选择好数据库)
source "sql的路径"
29.什么是sql注入
通过注入一些特殊的字符,绕开sql的判断机制
30.简述left join和inner join的区别?
left join 左连接 以左表为主,右表为辅,完整查询左表所有数据,右表中不存在数据用null补充
inner join 内连接 查询左表右表共同存在的数据 select * from a,b where a.cid = b.id
31.SQL语句中having的作用
一般和group by连用,将分组之后的数据进行二次过滤用having
32.Mysql数据库中varchar和text最多能存储多少个字符?
varchar最多存储2**8 / 3个字符
text最多存储 2**8个字符
33.Mysql的索引方式有几种?
主键索引
联合索引
辅助索引
34.什么时候索引会失效(有索引但无法命中索引)
1.如果查询的是一个大范围内的数据
2.用了or关键字
3.索引字段参与运算
4.使用like以%开头,
5.联合索引中,不符合最左前缀原则
35.数据库优化方案?
1.分表
2.读写分离
3.合理优化数据类型
36.什么是Mysql慢日志?
设定一个时间阈值,执行sql的时间超过该阈值,把该sql记录到慢日志中
第二部分
1.什么是IO多路复用
内部的实现就是异步非阻塞,通过单个线程管理多个socket连接,而不是创建大量的多进程或多线程,节省资源,提升效率
这些网络io都会被selector暂时挂起,推入内存序列
此时服务端可以任意处理调度里面的网络io
当连接的socket有数据的时候,自然会把对应的socket进行读写,而不至于一直阻塞等待io
2.async/await关键字的作用
asyncio是密集型任务中,处理协程异步并发的工具模块,目的是加快通信的速度,减少阻塞等待
async def 关键字定义异步的协程函数
await 关键字加载需要等待的操作前,控制一个可能发生io阻塞任务的切入和切出
3.数据库中有表:t_table_date
id tade_date
1 2018-1-2
2 2018-1-26
3 2018-2-8
4 2018-5-6
...
输出每个月最后一天ID
select id max(tade_date) from t_table_date group by month(tada_date)