网络编程
"""
一、 计算机网络
    将地理位置不同的,具有独立功能的多态计算机及外部设备,
    通过通信线路连接起来,从而实现信息和资源共享的计算机系统。
    
    计算机网络分为七层结构:
    应用层    跟人贴近
    表示层
    会话层
    传输层
    网络层
    数据链路层
    物理层   跟计算机贴近
"""
# 计算机的通信协议:是网络中计算机之间相互信息交流的一种规范,协议
"""
1. http,ftp  :应用层
2. tcp  udp  :传输层
       tcp:点对点之间的协议。安全可靠的协议。
       三次握手: 客户端说:我可以跟你连接吗
                 服务端说:可以
                 客户端说:我知道了
        udp:无连接协议,非安全可靠的协议。寄快递。
3. ip        :网络层
ip地址和端口号:
在网络连接中,确定网络地址独一无二,ip。
192.168.0.1      ===32个数据位。
端口号:一台计算机可能启动很多程序,多个进程,使用不同的端口号进行服务。
16位,
4. 硬件设备相关的协议
"""
"""
二、url
url:统一资源定位。
url:两个部分:
协议标识符、资源的名称
http(协议标识符)://www.baidu.com(资源名称)------注册好的域名
192.168.0.1:8080-----真正的访问地址
"""
"""
解析url
在python中使用urlparse函数,在urllib下,解析的结果可以分为六部分(元组):
协议、网络地址、路径、路径的参数、查询的参数、引用片段
特殊的ip:127.0.0.1(localhost):本地ip,本地回环地址。
"""
# 定义一个典型的地址
from urllib.parse import  urlparse
# 定义一个 典型的地址
url="http://127.0.0.1:9900/abc/index.html?name=admin&password=123"
result=urlparse(url)
print(result)
print(result[2])
 发送请求
 urllib.request模块的方法
# 两种方式
 1. urlopen(url)
from urllib.request import urlopen,urlretrieve
 urlopen向网络发起请求,参数指定url,返回值是一个响应对象,响应对象里包含服务器回应的信息
response=urlopen("http://www.sina.com.cn/")
# 服务器返回的内容,以字节形式返回
html=response.read()
html=html.decode()
print(html)
with open("d:/downloadfromsina.txt","wt") as f:
    f.write(html)
responseBaidu=urlopen("https://www.baidu.com/img/xinshouye_1aa582c0b96d57852497a8bbc4345f15.png")
with open("c:/baidu.Pic.png","wb") as f:
    f.write(responseBaidu.read())
# 伪造地址
responseBaidu=urlopen("file:///d:/abc.png")
with open("c:/abc.png","wb") as f:
    f.write(responseBaidu.read())
 2.urlretrieve直接将url定位的资源down
 第一个参数:url
 第二个参数:本地保存的地址
urlretrieve("https://www.baidu.com/img/xinshouye_1aa582c0b96d57852497a8bbc4345f15.png","c:/abc/baidu.Pic.png")
# 案例:可以对某一个地址下所有链接进行抓取
import re
url="https://www.csdn.net/"
rep=urlopen("https://www.csdn.net/")
content=rep.read().decode()
print(content)
res_url=r"<a.*?href=\"(https://.*?\".*?</a>"
urls=re.findall(res_url,content,re.DOTALL|re.MULTILINE|re.IGNORECASE)
for u in urls:
    print(u)
 
三、socket编程
"""
socket编程(套接字)
socket可以看成是连接点,每一个连接点都是一个socket
"""
# 使用socket编程实现客户端和服务端
"""
tcp 服务端
客户端发请求,socket
服务端监控请求,socket
当服务端监控有请求的时候,会产生一个新的socket,跟客户端进行沟通
"""
import socket
import threading
# 接受信息
def read(s):
    while True:
        print(s.recv(1024).decode())
# 发送信息
def write(s):
    while True:
        s.sendall(input().encode())
if __name__=="__main__":
    # 创建socket
    # 第一个参数:地址族
    # 第二个参数是通信的类型,TCP:socket.SOCK_STREAM,UDP
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 名字:bind绑定ip和端口,告诉外界,你的连接地址,注意传入一个元组
    s.bind(("127.0.0.1",8888))
    # 对客户端进行监听
    s.listen()
    # 如果客户端发送了请求,可以使用accept接受请求
    # accept函数可以返回两个内容:
    # 第一个新的socket(用来跟客户进行沟通)
    # 第二个远程的ip地址(客户端)
    so,addr=s.accept()
    print(so)
    print(addr)
    # 接受从客户端发送过来的信息
    # recv可以接受内容(字节),可以指定参数来指定接受的最大字节
    # recv在接受信息时,会一直处于阻塞状态。
    content=so.recv(1024)
    print(content.decode())
    # 服务端向客户端发送信息
    so.sendall(input("服务端说:").encode())
    # 目前只能说一句话
    while True:
        content=so.recv(1024)
        print(content.decode())
        content=input("服务端说:")
        so.sendall(content.encode())
        if content=="exit":
            break
    # 接受文件
    b=bytes()
    with open("d:/abc.txt","wb") as f:
        while True:
            data=so.recv(10)
            if not data:
                break
            # b+=data
            f.write(data)
    t1=threading.Thread(target=read,args=(so,))
    t2=threading.Thread(target=write,args=(so,))
    t1.start()
    t2.start()
tcp 客户端
# 新创建连接点socket
import socket
import threading
from day20.tcpserver import read,write
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 建立连接,发送请求
# connect方法建立连接,传入元组(ip,端口号),服务器地址
s.connect(("127.0.0.1",8888))
# 发送信息
s.sendall("发送一条信息".encode())
while True:
    content=input("客户端说:")
    s.sendall(content.encode())
    if content=="exit":
        break
    # 客户端接受从服务端传递过来的信息
    print(s.recv(1024).decode())
# 传送文件
with open("c:/abc.txt","rb") as f:
    s.sendfile(f)
t3=threading.Thread(target=read,args=(s,))
t4=threading.Thread(target=write,args=(s,))
t3.start()
t4.start()
udp 服务端
# udp服务端 不适合发送精准内容,不安全,也没有保障的协议。
# udp速度很快,适合超时之后,服务端就不需要接受。
# udp不需要进行监听
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(("127.0.0.1",8888))
print(s.recv(1024).decode())
udp 客户端
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# udp在客户端也不需要连接。
s.sendto("不需要连接,之间发送".encode(),(("127.0.0.1",8888)))