网络并发编程总结

2018-09-18 06:45:16来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

网络编程

 

一.

1.网卡:

  电脑中有网卡,网卡中有mac地址.

2.IP:

  插上网线,路由器或交换机中的DHCP服务会自动分配IP地址.

  IP:192.168.13.150

    IPv4:  

      00000000.00000000.00000000.00000000

      0-255  0-255  0-255  0-255

    IPv6:

      00000000.00000000.00000000.00000000.00000000.00000000

3.子网掩码:255.255.255.0

  IP:192.168.13.150

  子网掩码:255.255.255.0

4.网关:路由器中连接交换机的口

 网关IP:第一个IP地址

 

5.DNS:

  网络连接:

    1.域名解析:

      Windows电脑:先去本地的hosts文件中找IP

        C:Windows\System32\drivers\etc\hosts

      Linux/Mac电脑:

        /etc/hosts

    2.连接:

      sk = socket.socket()

      sk.connect(("127.0.0.1",8000))

    3.如果创业:

      1.租一个服务器+公网IP

      2.租域名:域名+IP解析

总结:

  IP:4个点分的十进制表示

  DHCP:自动为局域网内中的电脑分配IP

  网关:路由器中连接交换机的口

  子网掩码:将挡住的IP位数作为网段,未挡住的部分作为可变的值

    IP:192.168.13.15.

    子网掩码:255.255.255.0

  局域网,城域网,广域网

  arp协议:通过目标的IP地址,查找目标的mac地址

  DNS

 

二.

1.OSI模型:

  7层模型:

    应用层:使用软件

    表示层:看到数据,如图片,视频

    会话层:保持登录或链接状态

    传输层:TCP/UDP

    网络层:IP

    数据链路层:MAC

    物理层:将数据转换成电信号发送

  5层模型:

    应用层:应用层,表示层,会话层

    传输层

    网络层

    数据链路层

    物理层

  4层:

    应用层:应用层,表示层,会话层

    传输层

    网络层

    物理层L数据链路层,物理层

 

2.三次握手四次挥手

#三次握手:
1.客户端(Client)向服务端(Server)发送一次请求
2.服务端确认并回复客户端
3.客户端检验确认请求,建立连接
#四次挥手:
1.客户端向服务端发一次请求
2.服务端回复客户端(断开客户端-->服务端)
3.服务端再次向客户端发请求(告诉客户端可以断开了)
4.客户端确认请求,连接断开

断开连接时,反映到代码上就是抛出异常或发送空内容

 

三.

1.BS(Browser/Server)和CS(Client/Server)架构

BS:浏览器/服务器

CS:客户端/服务器

  a.CS架构是建立在局域网的基础上的,BS架构是建立在广域网的基础上的

  b.CS一般比BS安全

  c.CS更加注重流程,BS更加注重访问速度

  d.BS比CS能更好的重用

  e.CS比BS系统维护周期长,开销大

  f.CS多是建立在Windiws平台上,BS建立在浏览器上.

四.

1.socket代码:

    

 1 import socket
 2 服务端:
 3 server = socket.socket()
 4 server.bind(("127.0.0.1",8000))
 5 server.listen(5)
 6 conn,addr = server.accept()
 7 
 8 客户端:
 9 client = socket.socket()
10 client.connect(("127.0.0.1",8000))

2.黏包:

  1.发送数据时,每次发送的包小,因为系统进行优化算法,就将两次的包放在一起发送,减少了资源的重复占用,而客户端接收时,会一次全部接收

  2.接收数据时,多次接收,第一次接收的数据量小,导致数据还没接收完,就停下了,剩下的数据会缓存在内存中,然后等到下次接收时和下一波数据一起接收.

解决方案:

  1.先发送一个字节总大小,然后接收端循环接收所有数据.

  2.使用time模块

  3.先使用struct模块发送4个字节的文件大小,然后再发送数据.

 

3.协议:

  自定义协议:{"code":1001,"data":{...}}

  HTTP协议:GET /swd=alex HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n

    

并发编程

1.线程,进程,协程的区别:

 

 

2.进程:

 1 import multiprocessing
 2 
 3 def task(arg):
 4     print(arg)
 5 
 6 def run():
 7     p = multiprocessing.Process(target=task,args=(1,))
 8     p.start()
 9 
10 if __name__ == '__main__':
11     run()

 获取当前进程:name = multiprocessing.current_process()

进程间的数据共享:

 1 1.Queue
 2 
 3 import multiprocessing
 4 
 5 q = multiprocessing.Queue()
 6 
 7 def task(arg,q):
 8     q.put(arg)
 9 
10 def run():
11     for i in range(10):
12         p = multiprocessing.Process(target=task,args=(i,q))
13         p.start()
14 
15     while True:
16         v = q.get()
17         print(v)
18 
19 2.Manager
20 
21 import multiprocessing
22 
23 def task(arg,dic):
24     dic[arg] = 100
25 
26 if __name__ == '__main__':
27     m = multiprocessing.Manager()
28     dic = m.dict()
29     process_list = []
30     
31     for i in range(10):
32         p = multiprocessing.Process(target=taskargs=(i,dic))
33         p.start()
34         process_list.append(p)
35 
36     while True:
37         count = 0
38         for p in process_list:
39             if not p.is_alive():
40                 count += 1
41         if count == len(process_list):
42             break
43         print(dic)

进程锁:

 1 import time
 2 import multiprocessing
 3 
 4 lock = multiprocessing.RLock()
 5 
 6 def task(arg):
 7     print(111)
 8     lock.acquire()
 9     print(arg)
10     lock.release()
11 
12 if __name__ == '__main__':
13     p1 = multiprocessing.Process(target=task,args=(1,))
14     p1.start()
15 
16     p2 = multiprocessing.Process(target=task,args=(2,))
17     p2.start()

进程池

1 from concurrent.futures import ProcessPoolExcutor
2 
3 def task(arg):
4     print(arg)
5 
6 if __name__ == '__main__':
7     pool = ProcessPoolExcutor(5)
8     for i in range(10):
9         pool.submit(task,i)

 

3.线程

 1 import threading
 2 
 3 def task(arg):
 4     print(arg)
 5 
 6 for i in range(10):
 7     t = threading.Thread(target=task,args=(i,))
 8     t.start()
 9 
10 获取当前线程
11 ct = threading.current_thread()
12 
13 获取当前线程名字:
14 name = threading.getName()

线程锁:

 1 Lock:一次放一个,只能锁一次
 2 RLock:一次放一个,可以锁多次
 3 BoundedSemaphore(n):一次放n个
 4 Condition:一次放指定个
 5 Event:一次放所有
 6 
 7 import threading
 8 
 9 lock = threading.RLock()
10 
11 def task(arg):
12     lock.acquire()
13     print(arg)
14     lock.release()
15 
16 for i in range(10):
17     t = threading.Thread(target=task,args=(i,))
18     t.start()

线程池

1 from concurrent.futures import ThreadPoolExcutor
2 
3 def task(arg):
4     print(arg)
5 
6 pool = ThreadPoolExcutor(5)
7 for i in range(10):
8     pool.submit(task,i)

4.协程

 1 import greenlet
 2 
 3 def f1():
 4     print(111)
 5     g2.switch()
 6     print(222)
 7     g2.switch()
 8 
 9 def f2():
10     print(333)
11     g1.switch()
12     print(444)
13     g1.switch()
14 
15 g1 = greenlet.greenlet(f1)
16 g2 = greenlet.greenlet(f2)
17 g1.switch()

协程+IO

 1 from gevent import monkey
 2 monkey.patch_all()
 3 import requests
 4 import gevent
 5 
 6 def get_page1(url):
 7     ret = requests.get(url)
 8     print(ret.content)
 9 
10 def get_page2(url):
11     ret = requests.get(url)
12     print(ret.content)
13 
14 def get_page3(url):
15     ret = requests.get(url)
16     print(ret.content)
17 
18 gevent.joinall(
19     [
20     gevent.spwan(get_page1,'https://www.python.org/'),
21     gevent.spwan(get_page1,'https://www.yahoo.com/'),
22     gevent.spwan(get_page1,'https://github.com/'),
23 
24 
25 ]
26 
27 
28 )

threading.local的作用:为每个线程开辟一个空间进行数据存储,自己通过字典创建一个类似于threading.loacl

requests模块模拟浏览器发送请求:

  本质:

    requests.get(url)

    创建socket客户端

    连接,阻塞

    发送请求

    接收请求,阻塞

    断开连接

 

同步异步:

  同步过程中进程触发IO操作并等待或者轮询的去查看IO操作是否  完成

  异步过程中进程触发IO操作后直接返回做其他事情

阻塞非阻塞:

  应用请求IO操作时,需要等待就是阻塞,请求立即返回就是非阻塞.

  阻塞 -> 非阻塞:

    client.setblocking(False)

    会报错,需要try

    try:

      pass

    except BlockingIOError as e:

      pass

 

什么是异步非阻塞?

  非阻塞:不等待,比如创建socket对某个地址进行connect,获取接收数据recv默认都会等待(连接成功或接收到数据),才执行后续操作.如果设置setblocking(False),以上两个过程就不会再等待,但是会报BlockingIOError错误,只要捕获即可

  异步:通知,执行完成之后自动执行回调函数或自动执行某些操作.

 

什么是同步阻塞?

  阻塞:等待

  同步:按照顺序逐步执行.

  

 

IO多路复用:

  IO多路复用分为时间上的复用和空间上的复用

  空间上的复用是将内存分为几部分,每一部分放一个程序,这样同一时间内存中就有多道程序.

  时间上的复用是指多个程序在一个CPU上运行,不同的程序轮流使用CPU.

  当某个程序运行时间过长或者遇到IO操作,操作系统会把CPU分配给下一个程序,保证CPU处于高使用率,实现伪并发.  

IO多路复用作用:检测socket是否已经发生变化(是否已经连接成功/是否已经获取到数据)(可读/可写)

 

操作系统检测侧socket是否发生变化有三种模式:

  select:最多1024个socket,循环去检测

  pool:不限制监听socket个数,循环去检测(水平触发)

  epool:不限制监听个数,回调方式(边缘触发)

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Django项目快速搭建

下一篇:Python全栈Day 12部分知识点