python网络面试

第1题

OSI 网络七层模型: 应用层(应用层,表示层,会话层) 在应用层中封装实际的数据(http https ftp) 传输层: 封装端口 指定传输的协议(TCP / UDP) 网络层: 封装ip ipv4/ipv6 数据链路层: 封装mac地址, 指定链路层协议: arp(通过ip->mac) / rarp(通过mac->ip) 物理层: 打成数据包,变成二进制的字节流通过网络传输

交换机拆数据包,拆2层? 物理层 -> 数据链路层(mac地址) 路由器拆数据包,拆3层? 物理层 -> 数据链路层(mac地址) -> 网络层(ip地址) 交换机是在局域网内转发数据 路由器是在广域网内转发数据

第2题

SYN 创建连接 ACK 确认响应 FIN 断开连接

三次握手

客户端发送一个请求,请求建立连接
服务端接受客户端的请求,发出与客户端建立连接的响应
客户端接收到服务端的响应之后,回应服务端的请求
接下来互相发送数据

四次挥手

客户端发送一个请求,请求断开连接
服务端接受客户端的请求,发出响应
等到所有的数据收发完毕之后
服务端发送断开连接的请求
客户端接受服务端的请求,发出响应
等到2msl 最大报文生存时间后
客户端和服务端彻底断开连接

第3题

tcp 需要建立连接,传输可靠,速度慢,数据无边界面向字节流
udp 不需要建立连接,可靠性差,速度快,数据有边界面向数据包(报文)

第4题

# 黏包:
tcp协议是无边界的特点,导致分开发送的多条数据粘合在一起变成一条数据

# 现象:
(1) 发送端,数据少,时间间隔小,容易几条数据粘合在一起 (发的太快)
(2) 接收端,在缓冲区接受数据慢,容易导致多次发送的数据粘合在一起(接的太慢)

# 解决:
import struct:
# pack
把任意长度的数字变成居右4个字节固定长度的字节流
res = struct.pack("i",2100000000) # i => 代表当前转换的数据时整型
# unpack
把4个字节固定长度的字节流恢复成原来的数据,返回的是元组
res2 = struct.unpack("i",res)[0] # i => 把res转换成原来的整型int

思路:
先计算发送的数据大小是多少,
通过pack转化一下,发送给客户端
对面的客户端先用4个字节recv接受一下数据的长度
然后按照这个长度来接受接下来要发送的实际数据大小
然后服务端在发送真实的数据;

场景:
处理黏包的场景只有在即时通讯当中使用
如果在上传或者下载这个领域,不需要处理黏包.

第5题

b/s : Brower/Server 网站,小程序
c/s : client/Server 软件

第6题

一.TCP服务端

import socket
# 1.创建一个socket对象
sk = socket.socket()
# 2.绑定ip和端口号(在网络中注册主机)
sk.bind("127.0.0.1",9000)
# 3.开启监听
sk.listen()
# 4.建立三次握手
conn,addr = sk.accept()
# 5.收发数据的逻辑
conn.recv(1024)
conn.send(b"abc") # 二进制字节流
# 6.四次挥手
conn.close()
# 7.退换端口
sk.close()

TCP 客户端

import socket
# 1.创建一个socket对象
sk = socket.socket()
# 2.与服务器进行连接
sk.connect( ("127.0.0.1",9000) )
# 3.收发数据
sk.send(b'abc')
sk.recv(1024)
# 4.关闭连接
sk.close()

 

二.UDP服务端

import socket
# 1.创建一个socket对象
sk = socket.socket(type=socket.SOCK_DGRAM)
# 2.绑定ip和端口号(在网络中注册主机)
sk.bind( ( "127.0.0.1",9000) )
# 3.收发数据的逻辑
msg,cli_addr = sk.recvfrom(1024)# 必须要先接受数据
sk.sendto(b'abc' , cli_addr)
# 4.关闭连接
sk.close()

UDP客户端

import socket
# 1.创建一个socket对象
sk = socket.socket(type=socket.SOCK_DGRAM)
# 2.收发数据的逻辑
sk.sendto(b'abc' , ( "127.0.0.1",9000) )# 必须要发数据
msg,cli_addr = sk.recvfrom(1024)
# 3.关闭连接
sk.close()

三.TCP / socketserver 支持TCP的并发连接

import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
# 三次握手的连接对象
conn =self.request

if __name__ = "__main__":
server = socketserver.ThreadingTCPServer( ("127.0.0.1",9000) , MyServer)
server.serve_forever()
(sk.setsockopt允许端口重用,测试环境可以用;)

第7题

并发: 一个cpu同一时间执行多个程序 并行: 多个cpu同一时间执行多个程序 进程: 资源分配的最小单位,进程之间的数据彼此隔离,可以并发并行 from multiprocessing import Process 线程: 程序调度的最小单位,进程里面包含线程,线程之间共享一份资源,只能并发(GIL锁) from threading import Thread 协程: 协程用来实现线程在多任务之间的切换 yield import gevent;from gevent import monkey;monkey.patch_all() 就绪态 运行态 阻塞态

# (5) 终极大招 彻底解决不识别阻塞的问题
from gevent import monkey
monkey.patch_all() # 把下面所有引入的模块中的阻塞识别一下
import time
import gevent

def eat():
print("eat 1")
time.sleep(3)
print("eat 2")

def play():
print("play one")
time.sleep(3)
print("play two")

# 利用gevent.spawn创建协程对象g1
g1 = gevent.spawn(eat)
# 利用gevent.spawn创建协程对象g2
g2 = gevent.spawn(play)

# 阻塞,必须g1协程执行完毕为止
g1.join()
# 阻塞,必须gg协程执行完毕为止
g2.join()
print("主线程执行完毕 ... ")

第8题

GIL:全局解释器锁,为了保证数据的安全,只让多线程并发,不能并行
同一时间,程序中的多个线程只能由一个cpu执行
解决办法:
1.换个jpython或者pypy解释器,有兼容性问题
2.用多进程方式间接实现多线程的并行
历史遗留问题,无法彻底解决

第9题

IPC : 
1.管道Pipe(只能用于两个进程之间的通信) (了解)
2.Queue(用于多个进程之间通信)
3.文件 (共享数据)

q = Queue(3)
q.put(1) q.get()
put_nowait get_nowait() (linux有兼容性问题)
empty full qsize(队列长度)

第10题

    from concurrent.futures import ProcessPoolExecutor , ThreadPoolExecutor
# (1) 创建进程池对象
p = ProcessPoolExecutor()
p = ThreadPoolExecutor()
# (2) 异步提交任务
res = p.submit(func,参数1,参数2,参数3 .... )
# (3) 获取当前进程池返回值
res_new = res.result()
# (4) 等待所有子进程执行结束
p.shutdown()
print("主进程执行结束... ")

 

第11题

创建生成器:

# (1) 生成器表达式:  ( i for i in range(10))
# (2) 生成器函数 : 函数内含有yield 关键字,需要初始化才能用

def producer(): for i in range(100): # 0 1 2 3 4 5 6 .... n = yield i print("结果:",n ) def consumer(): # 初始化当前生成器函数 g = producer() # send可以类比next,第一次调用时,必须发送None,send给yield发送数据(上一个yield) g.send(None) for i in range(10): # 0 1 2 3 ... 9 res = g.send(i) print(res) consumer()

第12题

同步 : 代码从上到下依次执行(一条主线)

异步 : 无需等待当前任务执行完毕,下一个任务就开始执行了 场景:多线程,多进程(多条主线)

阻塞 : sleep , input , listen , recv ....

非阻塞 : 没有需要交互等待的代码,直接执行; 异步非阻塞: 场景发生在多进程/多线程 之间 没有任何io等待,同时执行任务 设置setblocking(False) (设置非阻塞 了解)

第13题

from threading import Lock
死锁,互斥锁,递归锁
死锁: 只上锁不解锁是死锁
例:
# (1)
lock = Lock()
lock.acquire()
lock.acquire()
print(1111)

# (2)
线程1
a = Lock()
b = Lock()
a.acquire()
b.acquire()

线程2
b.acquire()
a.acquire

线程1,拿着a锁枪b锁
线程1,拿着b锁枪a锁
出现逻辑死锁

# (3)递归锁,用来解决线上死锁现象;
a = b = RLock()
a.acquire()
a.acquire()

a.release()
a.release()

# 如何避免:
使用一把锁,尽量不要使用锁嵌套,避免发生逻辑上的死锁,
如果出现死锁现象,可以快速用递归锁解决

 

第14题

守护进程 , 守护线程

守护进程: 守护的是主进程(当主进程代码执行结束后,会立刻杀死守护进程) 守护线程: 守护的是所有线程(等所有线程都执行结束了之后,守护线程才会自动终止)

import threading import time def _wait(): time.sleep(60)

flag a

print("a") t = threading.Thread(target=_wait)

设置守护线程 t.setDaemon(True)

t.setDaemon(False)

t.start()

flag b

print("b")

第15题

import threading import time def _wait(): time.sleep(60)

flag a

print('1') t = threading.Thread(target=_wait) t.setDaemon(True) # 守护线程 t.start()

flag b

print('2')

第16题

import threading import time def _wait(): time.sleep(60)

flag a

t1 = time.time() t = threading.Thread(target=_wait) t.start() t.join() t2 = time.time()

flag b

print(t2-t1)

第17题 一定为0

import threading 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 = threading.Thread(target=add,args=(loop,)) ts = threading.Thread(target=_sub,args=(loop,)) ta.start() ta.join() ts.start() ts.join() print(number)

第18题 不一定

import threading loop = int(1E7) # 10000000.0 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 = threading.Thread(target=add,args=(loop,)) ts = threading.Thread(target=_sub,args=(loop,)) ta.start() ts.start() ta.join() ts.join() print(number)

def _add(loop = 1):

# global number
# for _ in range(loop):
# number += 1

def _sub(loop = 1):

# global number
# for _ in range(loop):
# number -= 1

第19题

myisam : 5.5之前默认的存储引擎 , 支持表级锁 innodb : 5.5之后默认的存储引擎 , 支持事务,行级锁,外键,可以抗住更大的并发 memory : 把数据临时放在内存中做缓存(读写速度快) blackhole: 黑洞,用来同步主从数据库,(主:增删改,从:查询)

第20题

对mysql数据库执行多条sql操作时,要么全部成功,如果出现失败直接回滚 begin; sql... commit; rollback;

A.原子性 同一个事务当中在执行多条sql时,要么全部成功,要么全部回滚,把这个过程看成一个整体,一个不能再继续分割的最小个体 C.一致性 按照约束插入数据,保持数据的一致 防止脏读,幻读,不可重复,保持数据的一致 I.隔离性 lock + isolation 锁,一个事务和另一个事务在操作过程中彼此隔离 D.持久性 把数据写在磁盘上,保证数据的持久化存储

第21题

脏读: 没提交的数据,别其他人读出来了 不可重读: 前后多次读取,数据内容不一致(正常来说:多个事务彼此隔里,看不见修改后的数据) 幻读: 前后多次读取,数据总量不一致(正常来说:多个事务彼此隔里,看不见新增或者删除的数据)

数据的隔离级别

RU(read-uncommitted) : 读未提交: 脏读 , 不可重读, 幻读 RC(read-committed) : 读已提交: 防止脏读,会出现不可重读和幻读 RR(repeatable-read) : 可重复读: 防止脏读,不可重复读,可能出现幻读(默认隔离级别) SR(serializable) : 可序列化: 什么都可以防止(不能异步并发,都是同步程序,性能差)

net stop mysql (超级管理员) net start mysql (超级管理员)

select @@tx_isolation

打开窗口1

begin; update t1 set name = "12334" where id = 1

打开窗口2

select * from t1;

第22题

char 定长,开辟空间速度快 varchar 变长,开辟空间速度慢 ( char和varchar会额外预留1~2个字节存储数据长度 如果没有设置成not null , 会额外预留1个字节做标记 )

第23题

varchar(50) 最多存储50个字符 字符长度小于255个,前头预留1个字节存储长度 字符长度大于255个,前头预留2个字节存储长度 ''' 1Byte = 8bit 1B = 8b 0000 0000 -> 0 1111 1111 -> 255 1111 1111 1111 1111 -> 65535 '''

第32题

varchar 21845字符 -> 65535字节 text 10485760字符 -> 31457280字节

第24题

delete 删除数据 truncate 重置表(删除数据+重置id)

第25题

a , ab ,abc (a) 命中 (b) 不行 (c) 不行 (a,b) 命中 (b,c) 不行 (a,c) 不行 (a,b,c) 命中

第26题

最左前缀原则, 必须含有最左边第一个字段 index(a,b,c) => a a,b a,b,c实际创建了3个索引

第27题

count avg max min select now() concat concat_ws select user() database() year(字段),month(字段),day(字段),hour,minute,second,week..... password

第28题

导出(\q退出数据库)

mysqldump -uroot -p123 db1 > db1.sql mysqldump -uroot -p123 db1 表1 表2 表3 > db1.sql

导入(进入到系统中,选好对应的数据库)

source 路径/abc.sql

第29题

sql注入:通过注入一些特殊的字符,可以绕开sql的条件和判断

使用mysql的预处理机制,可以最大程度避免sql注入

execute 默认参数是一条sql语句,如果加入参数元组,等于开启预处理 execute(sql, (参数1,参数2,参数3...) )

第30题

left join 左联 以左边为主,右表为辅,完整查询左表所有数据,右表不存在的数据拿null来补 inner join 内联 查询左表和右表共同存在的数据 select * from a,b where a.cid = b.id

第31题

一般和group by 配合使用,将分组之后的内容进行二次过滤用having

第33题

主键/联合主键:primary key(字段1,字段2,字段3) 唯一索引/联合唯一索引unique(字段1,字段2,字段3...) 普通索引/联合普通索引index(字段1,字段2,字段3...)

innodb(聚集索引) : 一个表只有一个聚集索引,和多个辅助索引 myisam(非聚集索引,辅助索引) : 没有聚集索引,只有辅助索引

myisam 和 innodb 使用的数据结构都是b+树,只是叶子节点存储的数据不同 innodb 文件结构中只有.frm(表结构) 和 .ibd(数据+索引) 两个文件,把索引和数据直接放到叶子节点中了 myisam 文件结构中有.frm .myd .myi 叶子节点存储的是索引值,以及映射出来的id

第34题

1.如果查询的是一个大范围内的数据(like > < >=  in between and ..) 不能命中索引
2.索引字段参与运算,不能命中索引的.例:select * from t1 where id*3 = 3000
3.如果有or 相连,索引字段在or条件中不能命中索引
4.类型不匹配,不能命中 select * from s1 where name = 1111
5.联合索引,不符合最左前缀原则,不能命中
6.like 以%od开头 不能命中.

第35题

1.读写分离(主从数据库,主数据库增删改,从数据库负责查询)
2.分库分表(将表字段或者表数据进行竖切或者横切)
3.优化数据模型,尽量改善b+树这个数据结构的高度,追求矮胖结构

第36题

设定一个时间阀值,时间超过这个阀值,把该sql记录在文件日志里,就是慢日志
# 查看日志的开启状态
show variables like "slow_query_log";
# 开启慢日志
set global slow_query_log = "ON";
# 查看时间阀值
show variables like "long_query_time";
# 设置时间的阀值
set global long_query_time = 5;

第37题

teacher 教师 id name post_id 1 王老师 3 2 张老师 4

class 班级 id name 1 python28 2 python29 3 python30

t_c_relation 多对多的关系表 id tid cid 1 1 1 2 1 2 3 1 3 4 2 1 5 2 2 6 2 3

student 学生 id name class_id 1 张三 1 2 李四 2

post 部门(科室) id name parent_id 1 教学部 0 2 教务部 0 3 python 1 4 linux 1 5 班主任 0

a

select count(*) from t_c_relation as tc,student as s where tc.cid = s.class_id and tc.tid = 1

b

select count(*) from post where parent_id = 3

c.

select tc.tid, count(*) as c from t_c_relation as tc,student as s where tc.cid = s.class_id group by tc.tid order by c desc limit 1

 

第38题

staff sid sname sex 1 张三 男 2 李四 女

course cid cname 1 计算机 2 美术 3 数学

sc_relation(多对多) sid cid 1 1

select s.sname from staff as s, course as c, sc_relation as sc, where s.sid = sc.sid and c.cid = sc.cid and c.cname = "计算机" and s.sex = "男"

第一题:

传统方法,使用多进程并发模型,没进来一个新的i/o流都会单独去分配一个新的进程管理(开辟出无限个进程,增加系统负担,导致崩溃死机) 后来使用i/o多路复用(利用单个线程,通过记录和跟踪每个i/o流状态,来同时管理多个i/o连接) select , poll ,epoll 都是i/o多路复用的具体实现.

第二题

asyncio 是在io密集型任务中,处理协成异步并发的工具,目的加快通信速度,减少阻塞和等待 async def 关键字定义一步的协成函数 await 控制协程任务在发生io阻塞时的切入和切出(任务切换)

第三题

执行计划 在一条sql执行之前,制定执行的方案
explain/desc + sql
desc select * from 表
执行计划的类型, 优化级别从低->高
all < index < range < ref < eq_ref < const < system
目标: 至少达到range,ref:
range : 索引范围中的扫描(小范围,否则大范围无法命中索引)
ref   : 普通索引查询(非唯一)

第四题

慢日志:https://www.cnblogs.com/Yang-Sen/p/11384440.html

第四题:https://www.cnblogs.com/Eva-J/articles/10435035.html

第五题

查询月份

select max(bb) as mx from ceshi123 group by month(bb)

联表

select id,bb from ceshi123 as c123 inner join (select max(bb) as mx from ceshi123 group by month(bb)) as ccc on c123.bb = ccc.mx

posted @ 2020-07-23 18:19  郝雲凯  阅读(93)  评论(0)    收藏  举报