第九篇:网络编程补充与进程

本篇内容

  1. udp协议套接字
  2. 开启进程的方式
  3. 多进程实现并发的套接字通信
  4. join方法
  5. 守护进程
  6. 同步锁
  7. 进程队列
  8. 生产者消费者模型
  9. 进程池
  10. paramiko模块

一、 udp协议套接字

1.TCP和UDP在传输层区别:
UDP是无连接不可靠的数据报协议。TCP提供面向连接的可靠字节流。

2.使用UDP常见应用:
DNS(域名系统),NFS(网络文件系统),SNMP(简单网络管理协议)。

3.代码应用:

服务端:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import socketserver
class MyUDPhandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.request)
        self.request[1].sendto(self.request[0].upper(),self.client_address)

if __name__ == ‘__main__‘:
    s = socketserver.ThreadingUDPServer((‘127.0.0.1‘,8080),MyUDPhandler)
    s.serve_forever()

客户端:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from socket import *

udp_client = socket(AF_INET,SOCK_DGRAM)

while True:
    msg=input(‘>>: ‘).strip()
    udp_client.sendto(msg.encode(‘utf-8‘),(‘127.0.0.1‘,8080))
    data,server_addr = udp_client.recvfrom(1024)
    print(data.decode(‘utf-8‘))

注意:但这种方式并不能控制客户端的并发数量,并发数量达到一定数量后,服务端会down掉,解决办法后续会提供。

二、开启进程的方式

开启进程的方式分为两种:

(1)利用模块开启进程:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Process
import time
def work(name):
    print(‘task <%s> is runing‘ %name)
    time.sleep(2)
    print(‘task <%s> is done‘ % name)

if __name__ == ‘__main__‘:
    p1 = Process(target=work,args=(‘xiaolan‘,))
    p2 = Process(target=work,args=(‘xiaohong‘,))
    p1.start()
    p2.start()
    print(‘主程序‘)

(2)利用类开启进程:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Process
import time

class MyProcess(Process):
    def __init__(self,name):
        super().__init__()
        self.name = name

    def run(self):
        print(‘task <%s> is runing‘ % self.name)
        time.sleep(2)
        print(‘task <%s> is done‘ % self.name)

if __name__ == ‘__main__‘:
    p = MyProcess(‘xiaolan‘)
    p.start()
    print(‘主程序‘)

三、多进程实现并发的套接字通信

基于刚刚学习的开启进程的方式,咱们就用进程的方式来开启一个网络通信。

服务端:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Process
from socket import *

s = socket(AF_INET,SOCK_STREAM)
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind((‘127.0.0.1‘,8080))
s.listen(5)

def talK(conn,addr):
    while True:
        try:
            data=conn.recv(1024)
            if not data:break
            conn.send(data.upper())
        except Exception:
            break
    conn.close()

if __name__ == ‘__main__‘:
    while True:
        conn,addr = s.accept()
        p=Process(target=talK,args=(conn,addr))
        p.start()

    s.close()

客户端:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from socket import *

c = socket(AF_INET,SOCK_STREAM)
c.connect((‘127.0.0.1‘,8080))

while True:
    msg = input(‘>>: ‘).strip()
    if not msg:continue
    c.send(msg.encode(‘utf-8‘))
    data = c.recv(1024)
    print(data.decode(‘utf-8‘))

c.close()

四、join方法

1.定义:

(1)join方法的作用是阻塞主进程(挡住,无法执行join以后的语句),专注执行多进程。

(2)多进程多join的情况下,依次执行各进程的join方法,前头一个结束了才能执行后面一个。

(3)无参数,则等待到该进程结束,才开始执行下一个进程的join。

2.代码:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Process
import time

def work(name):
    print(‘task <%s> is runing‘ %name)
    time.sleep(3)
    print(‘task <%s> is done‘ % name)

if __name__ == ‘__main__‘:
    p1 = Process(target=work,args=(‘xiaolan‘,))
    p2 = Process(target=work,args=(‘xiaohong‘,))
    p3 = Process(target=work,args=(‘xiaolv‘,))

    p_list = [p1, p2, p3]
    for p in p_list:
        p.start()
    for p in p_list:
        p.join()
    print(‘主进程‘)

五、守护进程

1.定义:

(1)守护进程是主程序创建的。

(2)守护进程会在主进程代码执行结束后就终止。

(3)守护进程内无法再开启子进程,否则抛出异常:

AssertionError: daemonic processes are not allowed to have children。

2.代码:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Process
import time

def work(name):
    print(‘task <%s> is runing‘ %name)
    time.sleep(2)
    print(‘task <%s> is done‘ % name)

if __name__ == ‘__main__‘:
    p1 = Process(target=work,args=(‘xiaolan‘,))
    p1.daemon = True
    p1.start()
    print(‘主程序‘)

六、同步锁

1.定义:

通常被用来实现共享资源的同步访问,为每一个共享资源创建一个Lock对象当你需要访问该资源时,调用qcuqire方法来获取锁对象(如果其他线程已经获得该锁,则当前线程需等待期被释放),待资源访问完后,在调用release方法释放锁。

2.代码:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Process,Lock
import time
def work(name,mutex):
    mutex.acquire()
    print(‘task <%s> is runing‘ %name)
    time.sleep(2)
    print(‘task <%s> is done‘ % name)
    mutex.release()

if __name__ == ‘__main__‘:
    mutex = Lock()
    p1 = Process(target=work,args=(‘xiaolan‘,mutex))
    p2 = Process(target=work,args=(‘xiaohong‘,mutex))
    p1.start()
    p2.start()
    print(‘主程序‘)

3.代码应用:

模拟抢票过程

python代码:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import json
import os
import time
from multiprocessing import Process,Lock

def search():
    dic = json.load(open(‘db.txt‘))
    print(‘\033[32m[%s] 看到剩余票数<%s>\033[0m‘ %(os.getpid(),dic[‘count‘]))

def get_ticket():
    dic = json.load(open(‘db.txt‘))
    time.sleep(0.5) #模拟读数据库的网络延迟
    if dic[‘count‘] > 0:
        dic[‘count‘] -= 1
        time.sleep(0.5)  # 模拟写数据库的网络延迟
        json.dump(dic,open(‘db.txt‘,‘w‘))
        print(‘\033[31m%s 购票成功\033[0m‘ %os.getpid())

def task(mutex):
    search()
    mutex.acquire()
    get_ticket()
    mutex.release()

if __name__ == ‘__main__‘:
    mutex = Lock()
    for i in range(10):
        p = Process(target=task,args=(mutex,))
        p.start()

db.txt文件:

{"count": 0}

4.缺点:

(1)运行效率低

(2)需要自己加锁处理,操作繁琐

七、进程队列

1.定义:

(1)Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。

(2)maxsize是队列中允许最大项数,省略则无大小限制。

2.代码:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Queue

q = Queue(3)

q.put(‘first‘)
q.put(‘second‘)
q.put(‘third‘)

print(q.get())
print(q.get())
print(q.get())

八、生产者消费者模型

1.定义:

在工作中,大家可能会碰到这样一种情况:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模式。

2.优点:

(1)解耦。

(2)支持并发。

(3)支持忙闲不均。

3.代码:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Process, JoinableQueue
import time, os

def producer(q, name):
    for i in range(3):
        time.sleep(1)
        res = ‘%s%s‘ % (name, i)
        q.put(res)
        print(‘\033[45m<%s> 生产了 [%s]\033[0m‘ % (os.getpid(), res))
    q.join()

def consumer(q):
    while True:
        res = q.get()
        time.sleep(1.5)
        print(‘\033[34m<%s> 吃了 [%s]\033[0m‘ % (os.getpid(), res))
        q.task_done()

if __name__ == ‘__main__‘:
    q = JoinableQueue()
    p1 = Process(target=producer, args=(q, ‘红烧肉‘))
    p2 = Process(target=producer, args=(q, ‘鱼香肉丝‘))
    p3 = Process(target=producer, args=(q, ‘锅包肉‘))
    c1 = Process(target=consumer, args=(q,))
    c2 = Process(target=consumer, args=(q,))
    c1.daemon = True
    c2.daemon = True
    p1.start()
    p2.start()
    p3.start()
    c1.start()
    c2.start()
    p1.join()
    print(‘主程序‘)

九、进程池

1.定义:

Pool可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

2.代码:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from multiprocessing import Pool
import os
import time

def work(n):
    print(‘task <%s> is runing‘ % os.getpid())
    time.sleep(2)
    return n**2

if __name__ == ‘__main__‘:
    p = Pool(4)
    res_l = []
    for i in range(10):
        res = p.apply_async(work,args=(i,))
        res_l.append(res)
    p.close()
    p.join()

3.进程池之回调函数:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import requests
import os,time
from multiprocessing import Pool

def get_page(url):
    print(‘<%s> get :%s‘ % (os.getpid(), url))
    respone = requests.get(url)
    if respone.status_code == 200:
        return {‘url‘: url,‘text‘: respone.text}

def parse_page(dic):
    print(‘<%s> parse :%s‘ % (os.getpid(), dic[‘url‘]))
    time.sleep(0.5)
    res = ‘url:%s size:%s\n‘ % (dic[‘url‘], len(dic[‘text‘]))
    with open(‘db.txt‘, ‘a‘) as f:
        f.write(res)

if __name__ == ‘__main__‘:
    p = Pool(4)
    urls = [
        ‘https://www.baidu.com‘,
        ‘https://www.qq.com‘,
        ‘https://www.163.com‘,
        ‘https://www.sina.com‘,
        ‘https://www.jd.com‘,
        ‘https://www.taobao.com‘,
        ‘https://www.sohu.com‘,
    ]

    for url in urls:
        p.apply_async(get_page, args=(url,), callback=parse_page)
    p.close()
    p.join()
    print(‘主进程pid:‘, os.getpid())

十、paramiko模块

1.定义:

paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。

由于使用的是python这样的能够跨平台运行的语言,所以所有python支持的平台,如Linux, Solaris, BSD, MacOS X, Windows等,paramiko都可以支持,因此,如果需要使用SSH从一个平台连接到另外一个平台,进行一系列的操作时,paramiko是最佳工具之一。

2.安装:

由于paramiko是第三方模块,所以是需要我们单独安装的。

pip3 install paramiko

3.代码:

(1)使用密码连接的方式:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=‘192.168.0.1‘, port=22, username=‘root‘, password=‘root123456‘)

stdin, stdout, stderr = ssh.exec_command(‘df -h‘)
result = stdout.read()
print(result.decode(‘utf-8‘))
ssh.close()

(2)使用秘钥连接的方式:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import paramiko

private_key = paramiko.RSAKey.from_private_key_file(‘id_rsa‘)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=‘192.168.0.1‘, port=22, username=‘root‘, pkey=private_key)

stdin, stdout, stderr = ssh.exec_command(‘df‘)
result = stdout.read()
print(result.decode(‘utf-8‘))
ssh.close()

(3)上传或下载文件:

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import paramiko

transport = paramiko.Transport((‘192.168.0.1‘, 22))
transport.connect(username=‘root‘, password=‘root123456‘)

sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put(‘test.txt‘, ‘/tmp/test.txt‘)
sftp.get(‘/tmp/test.txt‘, ‘test.txt‘)
transport.close()
时间: 2024-10-22 21:40:59

第九篇:网络编程补充与进程的相关文章

iOS开发网络篇—网络编程基础

iOS开发网络篇—网络编程基础 一.为什么要学习网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过网络跟外界进行数据交互.数据更新,应用才能保持新鲜.活力 (3)如果没有了网络,也就缺少了数据变化,无论外观多么华丽,终将变成一潭死水 移动网络应用 = 良好的UI + 良好的用户体验 + 实时更新的数据 新闻:网易新闻.新浪新闻.搜狐新闻.腾讯新闻 视频:优酷.百度视频.搜狐视频.爱奇艺视频 音乐

[Python网络编程]浅析守护进程后台任务的设计与实现

在做基于B/S应用中,经常有需要后台运行任务的需求,最简单比如发送邮件.在一些如防火墙,WAF等项目中,前台只是为了展示内容与各种参数配置,后台守护进程才是重头戏.所以在防火墙配置页面中可能会经常看到调用cgi,但真正做事的一般并不是cgi,比如说执行关机命令,他们的逻辑如下: (ps:上图所说的前台界面包含通常web开发中的后端,不然也没有socket一说) 为什么要这么设计 你可能疑惑为什么要这么设计,我觉得理由如下: 首先有一点说明,像防火墙等基本上都运行在类Linux平台上 1.安全问题

C#网络编程基础之进程和线程详解

在C#的网络编程中,进程和线程是必备的基础知识,同时也是一个重点,所以我们要好好的掌握一下. 一:概念 首先我们要知道什么是"进程",什么是"线程",好,查一下baike. 进程:是一个具有一定独立功能的程序关于某个数据集合的一次活动.它是操作系统动态执行的基本单元, 在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元. 线程:是"进程"中某个单一顺序的控制流. 关于这两个概念,大家稍微有个印象就行了,防止以后被面试官问到. 二:进程

网络编程三---多线程/进程解决并发问题

前文列出的代码给大家展示了一个最简单的网络程序,但正如文章末尾所提的,这个最简单的网络程序最大的缺点是服务端一次只能服务一个客户端,就比如说你去吃饭,饭店只有一个服务员, 而且服务员在客户离开之前只能为一个客户服务,也就是说你只能等待你前面的客户吃好饭离开了,然后你才能进去吃饭,而在你吃饭的时候时候,你后面来的人都得等你吃完饭才能轮到你后面一个人吃饭.这种模式的缺点很明显,因为在你进去点好菜到买单前的这段时间,这个服务员都是空闲的,为什么不让服务员在这个空闲时间让其他客户进来服务员为他点菜呢?在

《网络编程》守护进程

前言 守护进程是在后台运行并独立于所有终端控制的进程.守护进程没有控制终端源于它们通常是由系统初始化脚本启动,但是也有可能从某个终端由用户在 shell 提示符下键入命令行启动,这种启动方式的守护进程必须亲自脱离与控制终端的关联,从而避免与作业控制.终端会话管理.终端产生信号等发生任何不期望的交互,也可以避免在后台运行的守护进程非预期地输出到终端.有关作业控制.终端控制的内容可参考文章<作业控制.终端控制 和 守护进程> 由于守护进程没有控制终端,当守护进程出错时,必须通过某种输出函数输出错误

python 网络篇(网络编程)

一.楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运行,你就会发现,这两个python的文件分别运行的很好.但是如果这两个程序之间想要传递一个数据,你要怎么做呢? 这个问题以你现在的知识就可以解决了,我们可以创建一个文件,把a.py想要传递的内容写到文件中,然后b.py从这个文件中读取内容就可以了. 但是当你的a.py和b.py分别在不同电脑上的时候,你要怎么办呢? 类似的机制有计算机网盘,qq等等.我们可以在我们的电脑上和别人聊天,可以在自己

java基础篇---网络编程(TCP程序设计)

TCP程序设计 在Java中使用Socket(即套接字)完成TCP程序的开发,使用此类可以方便的建立可靠地,双向的,持续的,点对点的通讯连接. 在Socket的程序开发中,服务器端使用serverSocket等待客户端的连接,对于Java的网络程序来讲,每一个客户端都使用一个socket对象表示. 在Java的网络程序中,客户端只要符合连接的通讯协议,那么服务端都可以进行接收. ServerSocket类主要用于服务器端程序的开发上,用于接收客户端的连接请求. Socket在服务器端每次运行时都

java基础篇---网络编程

一:IP与InetAddress 在Java中支持网络通讯程序的开发,主要提供了两种通讯协议:TCP协议,UDP协议 可靠地连接传输,使用三方握手的方式完成通讯 不可靠的连接传输,传输的时候接受方不一定可以接受的到 在Java中的所有网络程序的开发类都在java.net包中存在 IP地址简介 IP地址是指互联网协议地址(英语:Internet Protocol Address,又译为网际协议地址),是IP Address的缩写.IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络

(49)LINUX应用编程和网络编程之四 Linux进程全解

补充: 1.  C程序的执行过程: C编译器调用链接器,链接器设置可执行程序文件的启动起始地址(启动例程),启动例程获得内核传递来的 命令行参数和环境变量值,为调用main函数做准备.[实际上该启动例程常用汇编语言编写],如果将启动例程换做C语言就是:exit(main(argc,argv)); main(int argc,char *argv[],char *engv[]);argv为指向参数的各个指针所构成的数组. 2.exit做一些清理处理(标准IO库的清理关闭操作为所有打开的流调用fcl