网络通信学习

~当前用户的家目录

-r 是用来删除目录的
Ctrl + L 清屏 等于 clear命令
凡是木录 目录名后都跟上/
cd .. 切换到当前目录的上一级目录
cd . 原地踏步,切换到当前目录
cd ~切换到当前用户家目录 与 cd作用一样 cd~ == cd
cp 文件路径 文件名 目的路径 mv 与cp用法一样但是只有一份文件

bit--8-->Byte--1024-->KB--1024-->MB-->.....c'd

选项 -p 再创建嵌套目录的时候使用 表示自动创建父目录(parents)

-v 在cp中复制文件时使用 用来显示copy的路径
-i 在删除时提醒是否要删除
cat 文件名 直接显示全部内容
more 文件名 只显示一屏,余下的折叠起来显示已经显示的量
touch 创建已经存在的文件就可以更改文件的最后修改时间


重定向 把本应该输出在终端的结果输出到其它位置 (文件中)
command > 文件名 每次都覆盖以前的内容
command >> 文件名 把内容追加到之前文件内容的后面
cat 多个文件名 >> 文件名 把多个文件的内容合并到一个文件中输出到终端上(>>后跟一个新文件名可以创建这个文件)


管道 command1 | command2 把command1的输出当作输入给command2 |-->管道连接符

history 显示历史命令


链接文件ln
ln -s 软连接的名字 () 软连接类似于Windows的快捷方式
ln 原文件名 硬链接文件名 (和源文件一样大小,就是源文件的另一个名字)ls -i 那个数字就是硬链接数量

间接地访问或者修改源文件
软连接可以跨分区,连接目录.
跨目录创建链接需要指定绝对路径


grep 搜索文件中的内容
在文件中搜索想要查找的字符串
grep [选项] '要搜索的字符串' 文件名
-n显示匹配及行号
-i忽略大小写
-v求反
正则
^? 以什么开始
?$ 以什么结束
?[xy] ?x或者?y
x.y 匹配三个字符 .可以是出/n外的任意字母


find 查找文件
find 要查找的目录/ -name '文件名'
?匹配一个任意字符
*匹配任意字符
[xy]匹配两个不同的字符

tar 归档
打包 默认不压缩
tar -cvf xxx.tar 需要打包的文件名1234..
-c创建打包文件

打包压缩gzip
tar -zcvf xxx.zip 需要打包压缩的文件名1234..

解包
tar -xvf 包文件名

解压缩解包
tar -zxvf 打包压缩文件名

bzip2压缩
tar -jcvf 打包压缩文件名 需要打包压缩文件名 (打包并且压缩)

bzip2解压缩解包
tar -jxvf 需要解压缩解包的文件
-C 后面跟路径 表示解压缩到哪

zip压缩
zip 文件名
解压zip
unzip -d 需要解压的压缩文件菜单

修改文件权限
rw-rw-r--
rw- rw- r--
文件所属用户 同组用户的权限 访客的权限
user - u group - g other - o a - all 所有用户
字母法
chmod 用户名+/-/=权限 文件名
[augo] 所有人
数字法
r4 w2 x1 -0
chmod 777 文件名 -->所有与用户都是rwx

sudo 命令 以root用户的权限执行命令
安装软件需要使用sudo

password
设置用户密码

which 文件名
查看文件所在位置

exit退出当前用户

SSH 加密远程登陆
用户端和服务器端都需要的装SSH服务
ssh 用户名@IP地址

软件安装
sudo apt-get install 软件
卸载软件
suo apt-get remove 软件
离线安装
sudo dpkg -i 软件


vim
命令模式 输入指令
插入模式 i 进入输入模式 esc退出到命令模式 ZZ保存退出!
末行模式 :wq :x保存并退出 :q!强制退出不保存

在命令模式下:a在光标后面 i在光标前面 I在行首 A在行末 O在光标行的上一行新开一行 o在光标所在行的下一行新开一行
G光标到末行 gg光标到首行
行数yy 复制多行 x删除光标后字符 X删除光标前 行数dd剪切 p粘贴 u撤销 ctrl r反撤销 >>缩进 <<缩前 v选中需要操作的行进行操作
r 替换当前字符 R替换光标后的字符 %s/需要替换的数据/新数据/g-全部替换

-----------------------------------------------------------------------------------------------------
ip地址的作用
用以计算机之间的网络通信 标识收发双方的身份
ipv4 点分式 网络号.主机号
ipv6 未来发展趋势,中国很迫切
127.0.0.1 本地环回 测试本机网络功能是否正常 表示本机系统
修改网卡的ip地址 sudo ifconfig ens33 ip(0,1,255有特殊用途不能使用!)

ping ip/域名 测试本机与远程计算机的网络是否正常通畅

端口 标识计算机系统中的一个应用程序
知名端口 0-1023 http 80 ssh 22 https 443 程序要使用著名端口需要root权限
动态端口 随机分配,动态变化

netstat -an|grep ":端口号" 查看端口的占用情况
sudo lsof -i ":端口号" 查看占用端口的程序
-----------------------------------------------------------------------------------------------------
socket 套接字(网络插座) 封装了网络通信功能 对用户提供接口
网络通信都是套接字

套接字有不同的方式UDP TCP等
UDP 用户数据报协议-->无连接不可靠-->发送端无需确认接收端可以直接发送数据-可能导致丢包 基于数据报 如发短信


import socket

#1 创建udp套接字 模块名 类名 ipv4 udp的缩写
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

#2 设置接受方的ip和端口
accept_address = ("192.168.18.32", 8080)

#3 使用sendto关键字发送 内容 ip和端口
udp_socket.sendto("哒嘎好! 我系苦天落!".encode("utf8"), accept_address)

#4 关闭套接字
udp_socket.close()

解码的格式和编码的格式必须一致

发送并接受数据
import socket
# 创建套接字
udp_soct = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

udp_soct.sendto("哈哈v".encode(), ("192.168.18.32", 8080))
# 接收数据
recv_data, send_address = udp_soct.recvfrom(1024) # 这个参数表示每次接受的字节数
print("发送者是: %s 内容是: %s" % (str(send_address), recv_data.decode("gbk")))
# 关闭套接字
udp_soct.close()

绑定端口号
套接字名.bind("ip", port) ip为空的话就表示绑定本机所有ip
在使用套接字之前绑定
为程序持续服务,容易被他人发现

python的module模块文件和source源文件
源文件名是文件名就行
模块名需要满足标识符命名规则

UDP广播
ip地址后有255就是广播地址

----------------------------------------------------------------------------------------------------
Tcp网络通信
面向连接
建立连接- 数据通信-关闭连接

可靠传输
应答机制 ack(应答)
超时重传 在发送方有一个定时器
错误校验 CRC循环冗余校验
拥塞控制 发送方根据实时情况 动态调整决定发送数据的速度

基于字节流(最小单位是字节)

Tcp recv返回值
正常情况类就是发送的字节数据
断开连接 收到空<--->收到空字节 表示段开连接

Tcp客户端-----------------
import socket


def main():
# 1创建套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2链接服务器 地址(IP 端口)
tcp_socket.connect(("192.168.18.26", 8080))

# 3发送/接受数据
send_data = "要发送的数据"(默认是字节类型的数据)
tcp_socket.send(send_data.encode("utf8"))
# 查看返回的数据 对方断开连接返回的就是b''
recv_data = tcp_socket.recv(1024)
print(recv_data)
# 关闭套接字
tcp_socket.close()
# print = input()
if __name__ == "__main__":
main()

Tcp服务器--------------
import socket


def main():
# 创建服务器套接字 大堂经理 IPV4 基于字节流
sever_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定本地地址 供客户端进行链接
sever_socket.bind(("", 6765))
# listen 监听 主动变成被动 有客户端链接才启动
sever_socket.listen(128) # 128表示等待被服务的客户端的最大数量
while True:
# accept 等待接受客户端 转到业务员
print("我在等待客户端链接......")
# accept 的返回值是一个元组 里面包含跟客户端关联的套接字对象(业务员) 和 客户端的信息
client_socket, client_address = sever_socket.accept()
print("本次链接的客户端是: %s ----- %s" % (str(client_address)))
# 给客户端发送数据 Ack
client_socket.send("Welcome!!".encode("utf8"))
while True:
# 接受客户端的数据
rece_data = client_socket.recv(4096)
# 如果客户端发送的数据不为空
if rece_data:
# 打印接受道德数据
print("客户端发来的是:%s" % rece_data.decode("utf8"))
client_socket.send("请求已解决完成!!".encode("utf8"))
else:
# 如果客户端断开连接,返回的就是空,那么就执行下面的代码
print("本次服务的客户端已经断开链接!!!")
# 关闭服务客户端的套接字 业务员
client_socket.close()
break # 客户端断开连接,结束服务,跳出循环接收下一个服务器套接字转过来的客户端

# 关闭服务器的套接字 大堂经理 这个不能关闭!!服务器要24小时待机等待客户端的随时链接
# sever_socket.close()


if __name__ == "__main__":
main()

基于字节流
最小单位是字节,一次不需要接收完,下一此接收可以继续接收,一次接收的数据也有可能是对方多次发送的


------------------------------------------------------------------------
三次握手 建立连接的时候

C 我想与你建立连接SYN_SENT S
S 收到请求后应答ACK 请求建立连接SYN C
S 成功建立连接ACK S


SYN同步请求,建立连接
ACK应答,收到请求后应该回复ACK

listen (128)
Linux中表示已就绪队列长度即全连接长度
其它系统中表示全连接和半连接的总和
connect意义
发起并完成和服务器的三次握手
accept意义
从就绪队列(全连接队列)中取出一个全连接
-------------------------------------------------------------------------
四次挥手 断开连的时候

主 断开连接请求FINM 被
被 应答 主
被 断开连接请求FINN 主
主 应答 被


再次运行 address in used的问题 Tcp之分手的代价......
为了彻底断开连接 主动断开连接的一方必须有一个责任 保持套接字连接的资源(特别是端口)30s到2m不等的时间不释放 (一般是在服务器端使用,因为客户端一般不绑定端口)
彻底解决 地址重用-->创建服务器套接字对象之后--> 服务器套接字对象.setsockopt(socket.SOL_SOCK, socket.SO_REUSEADDR, 1)
------------------------------------------------------------------------


Http 超文本传输协议 用于web浏览器和web服务器之间传输网页资源的一套协议格式
B S 连接协议 底层是Tcp 端口是80
基于TCP/IP协议实现的应用层协议
一次请求(request) 一次相应(response)
浏览器主动发起请求 web服务器被动响应
多个资源就是多次请求多次响应

Http浏览器请求的基本流程
1 输入网址(http协议(端口) 域名 资源路径)
2 域名发给DNS服务器解析域名得到ip
3 建立和web服务器的连接
4 发送资源请求
5 web服务器根据请求读取相应数据 按照一定格式发送给浏览器
6 浏览器接收数据并且解析显示

url通常指的就是网址

TCP/IP协议有四层 OSI有七层(了解)

计算机网络 --- 物流网络
应用层Http 用户寄快递
传输层Tcp Udp 快递公司
网络层IP目标ip 中转站(根据收件人地址)
网络接口层 运输方式(飞机.铁路,汽车)


B >>我想要XX数据>> S
B <<请求结果和XX数据<< S

记忆模式 文本记忆4-5年 交流记忆20年

F12调出的界面
elements 查看网页结构
console 调试网页的js代码
source 跟服务器请求过那些资源
network 浏览器和服务器之间的通信过程

--------------------------------------------------------------------------------
Http请求报文格式说明

请求行 Request line
Get / Http/1.1-->请求方法/请求路径/协议版本

请求方法
Get 主要用于浏览器向服务器请求数据
Post 主要用于浏览器向服务器推送数(提交)据
Head 测试服务器是否正常工作

/请求路径
"/"表示web服务器主页(首页, 根目录)

协议版本
Http/1.1

请求头(键值对方式 头: 域名\r\n) 头, 域名都是字符串
Host:www.baidu.com
主机:服务器主机的域名/IP(:非默认端口)

Connection: Keep-alive
连接方式: 保持存活 --长连接-保持连接一直存活
close短链接,请求一次就关闭套接字

User-Agent:
用户代理 标识用户浏览器的身份
作用
1.服务器识别浏览,让网页适配浏览器
2.服务器反爬

Accept:
服务器可以接受的数据/文件 的类型

Accept-Encoding:
服务器可以接受的压缩格式,
优点:加快传输的效率
缺点:加重CPU负荷(以性能高换时间短)

Accept-Language:
服务器接受的语言

请求体[浏览器需要上传给服务器的数据] post请求方法时使用
请求体 是在两个"\r\n"之后存在

Http请求报文格式都是以 \r\n 结尾

请求报文的格式
Get方式
请求行[Get 资源路径 协议版本\r\n]
请求头[头名称:值\r\n]
空行[\r\n]

Post方式
请求行[Get 资源路径 协议版本\r\n]
请求头[头名称:值\r\n]
空行[\r\n \r\n]
请求体


--------------------------------------------------------------------------------
Http响应报文格式 response

响应行-(状态行)
Http/1.1 200 OK(协议版本 状态码 状态说明)
2xx 2开头的都是表示成功
3xx 3开头的表示重定向(将浏览器访问的地址重定向到指定的位置)
4xx 4开头的表示客户端请求错误
5xx 5开头的都表示服务器端错误

响应头
Connection: Keep-Alive
连接方式: 长连接-保持存活
Content-Encoding:gzip
内容压缩的方式 浏览器根据压缩方式进行解压

Server:服务器程序的名字
web服务器程序的名字 最常用的是nginx 性能高/易扩展

Date: 时间
格林威治时间(0时区的时间)

Content-Type:内容的类型/编码字符集
浏览器根据该字段对数据进行解析

Content-Language:语言
服务器发送过来的内容的语言

Content-Length: 字节长度
内容的长度:以字节为单位

空行(\r\n)

响应体
回复给浏览器的内容

响应报文格式
response_line 响应行="http/1.1 200 ok\r\n"
response_head响应头="服务器版本等\r\n"
response_body响应体="服务器发送给浏览器的内容"
空行[\r\n]
要发送的数据 = response_line + response_head + "\r\n" + response_body

Http1.1默认长连接 默认存活connection:keep-alive
一个连接多次使用
节约时间,用户量过大容易造成服务器过载导致服务器不可用(以性能换时间)
现行web服务器主要使用长连接

Http1.0默认短链接 默认关闭connection:close
管理简单
用户量比较大时造成服务器响应过慢 大量创建和销毁连接
--------------------------------------------------------------------------------
web服务器 nginx产品

自己写web服务器的意义:理解web服务器的工作流程

--------------------------------------------------------------------------------
CSS 用来设置网页样式

通过命令行指定端口的意义
不用修改源代码 降低和源代码的耦合度 更加安全

操作系统将命令行参数放到sys模块的argv变量中(argv是一个列表,每个元素都是字符串类型)
----------------------------------------------------------------------------------
多任务
目的: 同时执行多个任务 提高程序的运行效率
时间片: cpu分配给程序运行的一小段时间
两种形式 :并发-->在同一时间段 轮流切换 运行的多个任务(时间片轮转)
并行-->在同一时间点 不同cpu 运行的多个任务


线程:程序执行时的流程/分支(操作系统进行调用执行的基本单位)
默认只有一个流程/分支 即 主线程 新建的线程称为 子线程
-------------------------------------------------------------------------------------------------------------------
创建线程

创建线程的步骤:

需要导入threading模块 导入thread类
子线程实例对象 = threading.Thread(target=子线程要执行的函数名, args =("位置参数",),kwargs={"参数名":"实参值"})
子线程实例对象.start()
对象名.join() 等待子线程执行完成


target--入口
args--给线程函数传递位置参数,args 是一个元组
kwargs--给线程函数传递关键字参数,kwargs 是一个字典

子线程.join()方法等待子线程运行完成

-------------------------------------------------------------------------------------------------------------------
多线程之间的运行是无序的

获取当前程序中存在的线程
threading.enumerate()

子线程会在执行完代码之后退出
但主线程会一直存在
所以主线程会等待所有最线程运行结束后再退出

daemon线程(守护线程) 如果当前程序中 只剩下daemon线程 那么整个程序就会退出
设置daemon线程的方法
子线程名.setDaemon(True)
-------------------------------------------------------
自定义线程类的步骤

1创建一个类,让这个类继承(threading.Thread)类
2实现run(self)方法
3创建子线程的实例对象()
4子线程实例对象.start()
-------------------------------------------------------
start()只会调用run()方法
其它方法需要在run方法里面进行调用

-------------------------------------------------------
同一个进程的多个线程共享全局变量
资源竞争(数据竞争) 由于多线程共享数据, 多线程不加限制一起修改共享数据导致数据混乱
-------------------------------------------------------
使用互斥锁加限制进行解决 能够保证在任意时刻只有一个任务能够成功占有锁
创建 锁对象 =threading.Lock()
加锁 锁对象.acquire()
解锁 锁对象.release()

优点: 保证多线程能够正确修改全局变量的值
缺点: 容易造成死锁,导致程序阻塞(一个子线程acquire()了互斥锁之后没有进行释放)
-------------------------------------------------------
with语法(写入文件时的用法)
with open("文件路径+文件名", "模式") as 文件对象:
文件对象.write(数据)

自动申请和释放资源

with语法(互斥锁时使用方法)
with lock:
全局变量名的操作
-------------------------------------------------------
udp聊天器思路
1主线程input sendto
子线程 recvfrom

------------------------------------------------------
进程 进程 进程 进程 进程
------------------------------------------------------
进程 (操作系统进行 资源分配 的基本单位)
在一个正在运行的程序中默认有一个进程--(主进程)
新建的进程--子进程
在一个进程中默认存在一个线程(主线程)
-------------------------------------------------------
单任务(单进程 单线程 的程序)
多进程多线程都可以完成多任务
-------------------------------------------------------
进程的状态
新建
ready 就绪态:运行的条件都已经慢去,等待cpu执行(完事俱备,只欠时间片)
running 执行态:cpu正在执行其功能 (当时间片用完就会返回到就绪态),(调用阻塞的函数就会进入等待态)
blocked 等待态:等待满足其条件(满足条件时会返回到就绪态)
死亡
-------------------------------------------------------
创建进程
实例对象名 = multiprocessing.Process(target=要调用的方法名(入口), args=("位置参数",), kwargs={"键":"值"})
实例对姓名.start()
-------------------------------------------------------
查看进程id的两种方式
os.getpid()
multiprocessing.current_process().pid
-------------------------------------------------------
终端查看方法
ps aux | grep "*.py"
-------------------------------------------------------
获取当前进程的父进程的id
os.getppid()
主进程就是子进程的父进程

主进程的父进程就是IDE
-------------------------------------------------------
子进程实例对象.join() 括号了的参数表示等待的时间,不填是默认永久,单位是秒
子进程结束后回收子进程占用的资源
-------------------------------------------------------
子进程实例对象.terminate()不管任务是否完成直接结束子进程

子进程实例对象.name name参数 获得子进程的名字
-------------------------------------------------------
多个进程执行的顺序是无序的

多个 进程 之间不共享全局变量 资源分配的单位 一个进程一个独立的空间

主进程会在所有子进程运行完成后结束运行
-------------------------------------------------------
Queue 其实就是一个用于 (父子进程) 进程间相互通信 的先进先出的队列
创建Queue队列
队列实例对象名 = multiprocessing.Queue(队列的长度)
放数据 队列实例对象名.put(数据)
取数据 队列实例对象名.get()
判满 队列实例对象名.full()
判空 队列实例对象名.empty()

*** python 不能在子进程 中使用input()函数

get / put 参数说明
block参数 表示如果没有满足条件 是否阻塞等待
timeout参数 表示如果等待 等待的时常

进程池
工作模式

工程队模式
提前准备一批进程为用户提供服务 能够更快地响应用户的需求, 循环使用已经空闲的的进程为后续的用户提供服务(节约进程的 创建和销毁 的开销)

(包工头)控制进程:专门进行任务调度的进程 当前的主进程就是控制进程
(工人)工作进程:专门处理用户的各种需求的进程

使用步骤
1创建进程池--> 进程池实例对象名 = multiprocessing.Pool(工作进程的数量)
2往进程池中添加数据-->同步 进程池实例对象名.apply(func = 指定要调用的方法(入口),args=(位置参数),), kwds{键:值}||添加任务后等待执行
2往进程池中添加数据-->异步 进程池实例对象名.apply_async(func = 指定要调用的方法,args=(位置参数,), kwds{键:值})||添加任务后直接向下执行
3关闭进程池-->进程池实例对象名.close()
4等待所有任务执行完成-->进程池实例对象名.join()


进程
分配资源 的基本单位 资源开销大 性能很高 稳定性好 cpu密集型(科学计算)

线程
调度执行 的基本单位 资源开销小 性能次之 稳定性较差 io密集型 (网络程序/文件读写,输入/输出)

------------------------------------------------------------------------------------------
迭代 借助记录用户访问位置的对象(迭代器) 把容器中的数据全部访问到的过程
迭代器 记录用户在迭代过程中的位置信息的对象
可迭代对象 能够可以被迭代的对象(容器,)

迭代器开发的意义:
1用户只需要操作迭代器,不需要关心可迭代对象的操作方式 操作简单
每一种可迭代对象都提供响应的迭代器
2解耦和 面向数据操作>>>-->>>面向迭代器 数据有变化时只需要变迭代器 用户不受影响
降低了用户和数据的耦合度

可迭代的对象 : 提供数据(提供迭代器)
迭代器: 访问数据, 把数据提供给用户 ,自动记录位置信息

判断对象是否是可迭代对象
isinstance(对象名,collections.Iterable)
判断对象是否是迭代器对象
isinstance(对象名,collections.Iterator)

自定义可迭代对象
class Iterable:
在类里面定义__iter__方法 ,然后使用本类创建的实例对象就是可迭代对象
__iter__ 方法 提供用于获取数据的迭代器
def __inter__(self):


迭代器类型
class Iterator:
在类中实现了__iter__() 和 __next__() 方法 ,这个类创建的实例对象就是迭代器对象
def __init__(self, 数据): # 创建实例对象的传过来的参数
self.data = data
self.index = 0 #索引以0为始


def __iter__() 提供迭代器
return self # 自己即是迭代器

def __next__() 提供下一个元素的值 如果迭代完成抛出停止迭代异常 (会在for循环中被for捕获)
if self.index >= len(self.data): #如果index超出数据的长度表示迭代完成,就抛出停止迭代的异常
raise StopIteration
else:
ret = self.data[self.index]#数据是index对应的数据
self.index += 1 #让index加1获取下一个
return ret #返回数据


生成器
简介的迭代器
按照规律生成数据 存储规律 的特殊的迭代器
访问的是临时生成的有某种规律的数据

生成器表达式
数据 = (x for x in 可迭代的容器)
占用资源小

列表推导式
数据 = [x for x in 可迭代的容器]

生成器是可迭代类型

生成器函数
yield关键字
将普通函数变为生成器函数 ,
暂停代码执行,将变量的值返回给调用生成器对象的地方
再次唤醒生成器的时候,是从刚刚暂停的位置继续往下执行

普通方式调用函数函数并不会执行,会创建生成器对象

python3中生成器可以使用return python2 不支持
执行return 代码结束,不再向下执行, 执行yield再次唤醒生成器的时候从刚刚暂停的位置继续往下执行


next(), send() 都是从生成器代码中取出下一个元素的值

next()方法不能传参
send()在执行生成器代码 的时候传参, 但是在刚刚启动的时候只能传None

---------------------------------------------------------------------------------------------------
协程
不开辟新线程的情况下完成多任务 按照一定的交替顺序执行
协程是 用户的代码进行调度的
进程和线程 是操作系统内核进行调度的

yeild greenlet


gevent
基于greenlet实现
在gevent 中默认不会自动切换多任务 需要使用gevent中的monkey.patch_all()解决

gevent的使用步骤
import gevent
from gevent import mokey-->放在最上边(gevent官方规定)
monkey.patch_all() # 自定切换

创建协程(自动执行的代码)
协程对象名 = gevent.spawn(要执行的方法名,协程的参数)
协程对象名.join() # 一个一个join()
gevent.joinall() # 等待所有协程执行结束在结束


进程 线程 协程
资源消耗大 消耗一般效率高 消耗小效率高程序性能不太高
IO密集型 适合IO密集型
并发度不太高不超过6万 并发度高


UNIX 一切皆文件!

猜你喜欢

转载自www.cnblogs.com/yintaiping/p/10826909.html