day31 网络编程,多进程多线程

 

 

今天的内容需要好好整理,概念性的东西比较多,都是需要理解的,这些是基层的理解,后期的很多知识都是要建立在今天的概念基础上的,以下两点是核心内容,必须要理解,自己把自己理解的注释加在里面:

 

 进程就是程序正在运行的过程,

顾名思义,进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。

#一 操作系统的作用:
    1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口
    2:管理、调度进程,并且将多个进程对硬件的竞争变得有序

 这里需要牵扯到计算机的起源,最原始的计算机是机械时代的产物,异常庞大,几乎有一栋3层楼那么高,当你需要启动一个程序的时候需要手动去一个一个的拧上螺丝,然后接上各种电源线,等等的一些复杂线路的操作,然后再启动程序,那些复杂的螺丝线路之类的东西都是属于计算机的硬件操作,后来演变到电子时代,就有了操作系统的概念出现,它就是帮助我们人类去跟计算机沟通的一个中间介质,我们通过在操作系统上工作就减少了跟硬件的接触,发展到今天我们即便不懂硬件是什么一样可以操作电脑,就是因为有操作系统的存在,我们的所有程序和软件等都是基于操作系统而运行的,当我们打开一个qq软件的时候就是打开了一个正在运行的程序,即进程,这个过程的执行是:首先我们的硬件-----电脑里的硬盘,操作系统把硬盘里面的qq程序包读出来读取到内存里面,然后开始在操作系统上运行,然后我们就打开了qq,开始顺利的使用它。操作系统打开一个qq,还可以打开一个 浏览器还能打开一个文档,这些东西打开后都是跟qq一样被操作系统从硬盘的数据包中读取出来,然后加载到内存中,在操作系统里面运行它们,那么这个时候,我们的内存是有限的,我们的cpu也只有一个,这些软件都需要在这些的硬件中来执行,他们之间就资源共享了,共享就意味着会有竞争,会有冲突,那么如何来调整冲突就是我们的操作系统需要做的事情了。

所以,总结为以上两点,操作系统来帮助我们的各个软件来调节在硬件占用上的冲突问题,以及为我们跟复杂的硬件沟通建立纽带,让我们的操作更加便捷,简单。

 

 

 

 

#二 多道技术:
    1.产生背景:针对单核,实现并发
    ps:
    现在的主机一般是多核,那么每个核都会利用多道技术
    有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个
    cpu中的任意一个,具体由操作系统调度算法决定。
    
    2.空间上的复用:如内存中同时有多道程序
    3.时间上的复用:复用一个cpu的时间片
       强调:遇到io切,占用cpu时间过长也切,核心在于切之前将进程的状态保存下来,这样
            才能保证下次切换回来时,能基于上次切走的位置继续运行

这里简单总结就是多个程序同时打开的时候,作为用户可以感知到这些程序是同时在运行的且互相之间有隔离互不干扰。
是怎么做到的呢,是不是就是肉眼所见的那样呢,下面我们来具体说一说。所谓的多道技术就类似于以前的老唱片,那种有一道一道同心圆刻录在一张唱片上的物理介质
唱片是需要指针去读取内容,指针找到所要找的文件的具体位置然后把它读取出来,前提是你需要读取的内容都存在于这张唱片里面,然后你想切换文件就直接把指针的位置调整即可
我们的程序运行也是这样的,把需要的文件从硬盘中通过操作系统提取到内存,这样就提高了文件的执行速度,内存就相当于这个唱片,文件就类似于唱片里面的同心圆,
所谓 多并发就是,我们的一切指令都是通过操作系统来执行,它在执行的时候把指令传给cpu,然后最终是cpu来运行这些程序和文件,然后把结果同过操作系统返回给我们,就是我们看到的结果
多并发就是有很多个程序都被打开了然后你肉眼可以看到它们在同时运行,但是实际上并不是真的同时在运行,是彼此切换着在运行,只不过切换的速度异常快,间隔时间很短,我们根本无从感知到它。
那么到底它内部是一个什么样的操作方式呢,多个程序打开后因为cpu只有一个,所以这些程序需要需要按照操作系统的分配来依次完成执行操作,那么操作系统是怎么分配的呢
程序执行的时候并不是一直在执行的,就比如你的qq一挂一整天,但是你并不是在一直停留在它上面,你会去做别的事情,当你需要通过它联系谁或者传什么文件之类的,才会返回到它上面来,
我们的cpu也是这样的,这个程序在执行过程中会占用我们的cpu,但是当它在正常运行是遇到了停留,那么此时的cpu就会被释放出来,这里就实现了空间上的复用,同时会记录下它所停留的节点信息,以便后期停留结束后,接着返回来继续执行
遇到的停留就叫做io,这是专业名词。遇到io后操作系统会根据优先级原则把cpu从io中释放出来切换到其他程序, 比如a,当a在执行中遇到io后接着切换,到b,然后同理,只要遇到io就会接着切换到其他程序,
cpu在不断切换的同时会记录每次切换的节点,当io执行完后,cpu会立即返回到io的节点处,继续执行未完成的程序。就类似于做饭的时候都是多步同时进行的,先煮饭,电饭锅煮饭的时候插上电它自己就开始煮了,然后
在它煮饭的时候可以去把衣服扔到洗衣机里面洗,然后洗衣机转动的时候可以去切菜,然后扔到锅里煮菜,煮的时候可以把地拖了,碗洗了,都是同时进行的,这样可以节省更多的时间然后提高效率,在不断切换到其他的工作中的时候
要记住煮饭的时间,洗衣机的时间,锅里煮菜的时间,都要接上,根据完成的顺序来,菜先煮好后就先去把菜盛出来,衣服先洗好后就先把衣服拿出来, 这里就实现了时间上的复用

我们上面提到的一切都是基于一个cpu的时候的执行效果,所谓的并发就是你看起来程序是同时在执行然后并不是这样的,它的程序内部在cpu中有切换的的,不过是切换的速度很快肉眼无法捕捉的。
而并行就真的是一个cpu处理一个程序而已,当然了看起来跟并发的效果是一样的。
但是如果有2个cpu,然后这两个cpu在处理5个程序的时候,就是并发和并行同时发生了。这里再解释一下这种情况下cpu程序的切换就是根据这两个已经占用cpu的程序谁先遇到io然后谁就就被先释放出来,处理下一个程序按照优先级来。

需要补充的一点是我们刚刚上面提到的整个程序的并发也好并行也好,都是因为遇到io然后为了提高执行效率,这里还有一个原因,就是哪怕这个程序它就是会一直执行下去然后不会遇到io,那么此时我们还会为了提高执行效率而切换程序吗?
当一个程序一直在运行的时候你不切换它,执行效率是不会受到丝毫影响的,就好比我一直在学习一直在学习,我的效率是很高的,因为不间断,然后如果我的电脑死机了,我就要被迫终止学习了,那么我的效率就受影响了。
所以我们不会为了提高执行效率而切换一个程序的。
那么我们到底切换不切换呢,当然是要切换的,切换的目的不是为了提高效率,而是为了不让一个程序独占cpu,要让各个程序雨露均沾,尽管这样会降低执行效率也非这样不可。

进程:
http://www.cnblogs.com/linhaifeng/articles/7430066.html
还有udb协议:
from multiprocessing import Process
import time
def task(name):
    print('%s is running' %name)
    time.sleep(2)
    print('%s is done' %name)

if __name__ == '__main__':
    # Process(target=task,kwargs={"name":'egon'})
    p=Process(target=task,args=('egon',))
    p.start()
    print('')
View Code
s.recvfrom()        接收UDP数据
s.sendto() 发送UDP数据

udb协议发送数据不确认对方是否会收到,它发送的时候是不需要建立链接的,发送的数据都是打好的一个个数据包,里面不仅包含数据内容还有ip地址和端口,ip和端口是必须要包含在里面的,所以它打好的包是不会发空的,因为即便你发送空内容,还有ip和端口在里面,所以不为空,所以它不会有粘包的问题出现。然后 它速度非常快,比

tcp协议发送数据要快,它是不需要建立链接的,也不需要绑定,直接发送和接收就好了,所以快,然而它有它的缺陷

 

tcp协议会在发送的时候先把数据从硬盘读取到缓存空间里然后再传输到对方的缓存空间里,然后对方再从自己的缓存空间里面读取出来,这样一个过程就形成了 一次数据的传输,tcp它会等到对方成功读取了数据然后回复 一条信息说它接收到了,然后tcp才会接着发送下一条信息,然后于此同时它就清空了刚刚缓存的数据内容,因为已经成功发送了。

但是udp是不会这样的,它不跟你建立链接,也不管你是否有受到它发送过来的数据,它只顾着自己发送就够了,这样的情况就会导致数据的丢失,比如它发送了20个字节,而我这里只接收3个字节,那么剩余的17个字节就会丢失,它发送完之后就自己清空了自己的缓存空间,所以udb是不稳定的,但是它也有它的应用场景,比如聊天的时候,

你给对方发送一堆消息,然后对方即便不回复你也不影响你发送(别人都不稀罕看你发的啥),还有就是搜索引擎,因为要快,搜索就是比速度的,即便你这次没有收到我的消息,我再发一次就是了,我反正很快。



服务端
服务端udb协议:
from socket import *

server=socket(AF_INET,SOCK_DGRAM)
server.bind(('127.0.0.1',8083))

while True:
    data,client_addr=server.recvfrom(1024)
    print('客户端的数据: ',data)
    server.sendto(data.upper(),client_addr)
View Code
客户端:
from socket import *

client=socket(AF_INET,SOCK_DGRAM)

while True:
    msg=input('>>: ').strip()

    client.sendto(msg.encode('utf-8'),('127.0.0.1',8083))
    data,server_addr=client.recvfrom(1024)
    print(data.decode('utf-8'))
View Code

 

 




posted @ 2017-11-29 19:58  dream-子皿  阅读(116)  评论(0编辑  收藏  举报