美文网首页
Spider基础之网络编程

Spider基础之网络编程

作者: 嗒嘀嗒嗒嘀嗒嘀嘀 | 来源:发表于2020-03-05 23:41 被阅读0次

    学习自刘大拿的Python课程

    网络编程

    • 网络编程
    • 网络协议: 一套规则
    • 网络模型:
      • 七层模型-理论模型:任务分块,各司其职
        • 物理层:如网线、水晶接头等
        • 数据链路层:图像传输、电压等
        • 网络层
        • 传输层
        • 会话层:传之前打招呼
        • 表示层
        • 应用层:我们现在
      • 四层模型-实际应用
        • 链路层:接线
        • 网络
        • 传输层
        • 应用层
    • 每一层都有相应的协议负责交换信息或者协同工作
    • TCP/IP 协议族,说俗了,不全是
      • TCP/IP 是供已连接因特网的计算机进行通信的通信协议
      • TCP/IP 指传输控制协议/网际协议 (Transmission Control Protocol / Internet Protocol)。
      • TCP/IP 定义了电子设备(比如计算机)如何连入因特网,以及数据如何在它们之间传输的标准。
    • IP地址:负责在网络上唯一定位一个机器
      • IP地址分ABCDE类
      • 是由四个数字段组成,每个数字段的取值是0-255(数量肯定不够,以一层套一层的分级方式增加数量),所以有局域网、广域网
      • 192.168.xxx.xxx:表示局域网ip
      • 127.0.0.1:表示本机
      • IPv4(不太够用,所以有IPv6),
        IPv6(中国刚开始用)
    • 端口(机器中所有的软件都有一个端口号,为该软件的编码)
      e.x.发QQ,IP用来锁定机器,端口用来锁定软件
      • 范围: 0-65535
        • 知名端口:0-1023 安排了位置
        • 非知名端口:1024- 未被占用即可用
          常见知名端口 端口号
          HTTP 80
          FTP 21
          SSH 22
          MSG ICP 29
          MySQL 3306
          豆瓣上有较全的汇总 端口大全
          自己做,端口号往大了做,一万起

    TCP/UDP协议

    两者是挂号信与凭信的区别,前者类似当今快递,靠编号邮寄接受;后者类似送信,靠邮寄地址接收

    • UDP:非安全的不面向链接的传输
      • 安全性差
      • 大小限制64kb:超过的话就切断,无序
      • 没有顺序
      • 速度快
    • TCP
      • 基于链接的通信(传信之前建立虚拟通路,对方已知有信)
    • Socket编程:解决如何和对方通信,包括找着对方(IP+端口);发消息(UDP/TCP)
      • socket(套接字): 是一个网络通信的端点, 能实现不同主机的进程通信,网络大多基于Socket通信
      • 通过IP+端口定位对方并发送消息的通信机制
      • 分为UDP和TCP
        即时通讯一般用UDP
        通信有两端
      • 客户端Client: 发起访问的一方
        ① 建立程序 socket
        ② 发送消息(知道IP + port的绑定信息)
        ③ 等待反馈
      • 服务器端Server:接受访问的一方
        想要通信,服务端需要:
        ① 建立socket (用socket通信)
        ② port (提供连接外面的端口) + IP等信息 (绑定)
        ③ 接受访问
        ④ 反馈(不必须)

    UDP 编程

    • Server端流程
      • 1. 建立socket,socket是负责具体通信的一个实例
      • 2. 绑定,为创建的socket指派固定的端口和ip地址
      • 3. 接受对方发送内容
      • 4. 给对方发送反馈,此步骤为非必须步骤
    • Client端流程
      • 1. 建立通信的socket
      • 2. 发送内容到指定服务器
      • 3. 接受服务器给定的反馈内容
    • 服务器 案例01
    '''
    Server端流程
    1.建立socket,socket是负责具体通信的一个实例
    2.绑定,为创建的socket指派固定的端口和ip地址
    3.接受对方发送内容
    4.给对方发送反馈,此步骤为非必须步骤
    '''
    
    # socket模块负责socket编程
    import socket
    
    # 模拟服务器的函数
    def serverFunc():
        # 建立socket
        # socket.AF_INET:使用ipv4协议
        # socket.SOCK_DGRAM: 选择通信方式,使用UDP通信
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
        # 设置和绑定IP和port
        # 127.0.0.1: 这个IP地址代表的是机器本身
        # 7852: 随便的端口
        # 地址是一个tuple类型,(IP,port)
        addr = ("127.0.0.1", 7852 )
        sock.bind(addr)
    
        # 接收对方消息
        # 等待方式:死等,没有其他可能性
        # recvfrom接收的返回值是一个元祖(tuple),前一项表示数据,后一项表示地址
        # 参数的含义是缓冲区大小
        # rst = sock.recvfrom(500) 可以这么写
        data, addr = sock.recvfrom(500)
        # 直接将接收到的两个值 数据(这里是消息)和元祖(port + IP)赋值给两个参数
    
        # 发过来的数据是一个字节流(bytes流),需要解码
        print(data)
        print(type(data))
    
        # 将发送过来的字节流解码得到str格式内容
        # decode默认参数是utf8
        # text = data.decode()
        text = data.decode()
        print(type(text))
        print(text)
    
        # 给对方返回消息
        rsp = "Ich hab keine Hunge.(德语)"
    
        # 发送的数据需要编码成bytes格式
        # 默认是utf8
        data = rsp.encode()
        sock.sendto(data, addr)
    
    if __name__ == '__main__':
        print("Starting server.......")
        serverFunc()
        print("Ending server........")
    
    • 客户端 案例02
    '''
    Client端流程
    1. 建立通信的socket
    2. 发送内容到指定服务器
    3. 接受服务器给定的反馈内容
    '''
    
    import socket
    
    def clientFunc():
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
        text = "Do you want to have a date with me? "
    
        # 发送的必须是bytes格式
        data = text.encode()
    
        # 发送
        sock.sendto(data, ("127.0.0.1", 7852))
    
        # 等待对方给出反馈
        data, addr = sock.recvfrom(200)
        text = data.decode()
        print(text)
    
    if __name__ == '__main__':
            clientFunc()
    
    # 顺序:先启动Server案例01.py程序
    

    Server端运行结果

    Starting server.......
    b'Do you want to have a date with me? '
    <class 'bytes'>
    <class 'str'>
    Do you want to have a date with me? 
    Ending server........
    

    Client端运行结果

    Ich hab keine Hunge.(德语)
    

    有时候程序运行完了,并不意味着端口空闲,有可能还在别占用,所以想在此使用该端口会报错。

    • 服务器程序要求永久运行(不能死,也不崩溃,这也是Linux系统在服务区常用的原因),一般用死循环处理
    • 不死服务器版本,运行命令加入死循环 案例03
    if __name__ == '__main__':
          import time
          while 1:
                try:
                      serverFunc()
                except Exception as e:
                      print(e)
                time.sleep(1)
    

    TCP编程

    • 面向链接的传输,即每次传输之前需要先建立一个链接
    • 客户端和服务器端两个程序需要编写
    • Server端的编写流程
      建立socket负责具体通信,这个socket其实只负责接受对方的请求,真正通信的是链接后从新建立的socket
      绑定端口和地址
      监听接入的访问socket(一定时间内查询一次)
      接受访问的socket,可以理解接受访问即建立了一个通讯的链接通路(虚拟通道)
      接受对方的发送内容,利用接收到的socket接收内容
      如果有必要,给对方发送反馈信息
      关闭链接通路(关闭虚拟通路)
    • Client端流程
      建立通信socket
      链接对方,请求跟对方建立通路
      发送内容到对方服务器
      接受对方的反馈
      关闭链接通路
    • 案例04 服务器端
    import socket
    
    def tcp_srv():
        # 1. 建立socket负责具体通信,这个socket其实只负责接受对方的请求,真正通信的是链接后从新建立的socket
        # 需要用到两个参数
        # AF_INET: 含义同udp一致
        # SOCK_STREAM: 表明是使用的tcp进行通信
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2. 绑定端口和地址
        # 此地址信息是一个元组类型内容,元组分两部分,第一部分为字符串,代表ip,第二部分为端口,是一个整数,推荐大于10000
        addr = ("127.0.0.1", 8998)
        sock.bind(addr)
        # 3. 监听接入的访问socket
        sock.listen() # 等待时间可修改
    
        # 服务器死循环,永远接收请求
        while True:
            # 4. 接收访问的socket,可以理解接受访问即建立了一个通讯的链接通路
            # accept返回的元组第一个元素赋值给skt,第二个赋值给addr
            skt,addr = sock.accept()
            # 5. 接收对方的发送内容,利用接收到的socket接收内容
            # 500代表接收使用的buffersize
            #msg = skt.receive(500)
            msg = skt.recv(500)
            # 接收到的是bytes格式内容
            # 想得到str格式的,需要进行解码
            msg = msg.decode()
    
            rst = "Received msg: {0} from {1}".format(msg, addr)
            print(rst)
            # 6. 如果有必要,给对方发送反馈信息
            skt.send(rst.encode())
    
            # 7. 关闭链接通路
            skt.close()
            # 一次接通通道,完成多次传输再关闭通道,可以节省资源
    
    
    if __name__ == "__main__":
        print("Starting tcp server.......")
        tcp_srv()
        print("Ending tcp server.......")
    
    • 案例05 客户端
    import socket
    
    def tcp_clt():
        # 1. 建立通信socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2. 连接对方,请求跟对方建立通路
        addr = ("127.0.0.1", 8998)
        sock.connect(addr)
        # 3. 发送内容到对方服务器
        msg = "中文我好像也能懂"
        sock.send(msg.encode())
        # 4. 接收对方的反馈
        rst = sock.recv(500)
        print(rst.decode())
        # 5. 关闭连接通路
        sock.close()
    
    if __name__ == "__main__":
        tcp_clt()
    

    运行结果

    # Server
    Starting tcp server.......
    Received msg: 中文我好像也能懂 from ('127.0.0.1', 57990)
    
    # Client
    Received msg: 中文我好像也能懂 from ('127.0.0.1', 57990)
    

    FTP编程

    • FTP(File Transfer Protocol)文件传输协议
    • 用途: 定制一些特殊的上传下载文件的服务
    • 用户分类: 登陆FTP服务器必须有一个账号
      • Real账户: 注册账户
      • Guest账户: 可能临时对某一类人的行为进行授权
      • Anonymous账户: 匿名账户,允许任何人
    • FTP工作流程
    端口 方向
    21 客户端 → 服务端
    22 服务端 → 客户端
    • 客户端链接远程主机上的FTP服务器
    • 客户端输入用户名和密码(或者“anonymous”和电子邮件地址)
    • 客户端和服务器进行各种文件传输和信息查询操作(客户端向服务器发起的一些命令)
    • 客户端从远程FTP服务器退出,结束传输
    • FTP文件表示
      分三段表示FTP服务器上的文件
      • HOST: 主机地址,类似于 ftp.mozilla.org, 以ftp开头 (mozilla.org表明是谁家的服务器)
        (url的访问地址一般为www.mozilla.orgmozilla.org为火狐的母公司,)
      • DIR:目录, 表示文件所在本地的路径,例如 pub/android/focus/1.1-RC1/
      • File:文件名称, 例如 Klar-1.1-RC1.apk

    如果想完整精确表示ftp上某一个文件,需要上述三部分组合在一起

    • 案例06
    # 需要导入相应包,主要是ftplib
    import ftplib # 关于FTP的操作都在这个包里边
    import os
    import socket
    
    # 三部分精确表示在ftp服务器上的某一个文件
    # 好多公开ftp服务器访问会出错或者没有反应
    HOST = "ftp.acc.umu.se"
    DIR = 'Public/EFLIB/'
    FILE = 'README'
    
    # 1. 客户端链接远程主机上的FTP服务器
    try: # 远程连接服务器有可能出现问题,所有一般要try
        f = ftplib.FTP()
        # 通过设置调试级别可以方便调试
        f.set_debuglevel(2)
        # 链接主机地址
        f.connect(HOST)
    except Exception as e:
        print(e)
        exit()
    print("***Connected to host {0}".format(HOST))
    
    
    
    # 2. 客户端输入用户名和密码(或者“anonymous”和电子邮件地址)
    try:
        # 登录如果没有输入用户信息,则默认使用匿名登录
        f.login()
    except Exception as e:
        print(e)
        exit()
    print("***Logged in as 'anonymous'")
    
    
    # 3. 客户端和服务器进行各种文件传输和信息查询操作
    try:
        # 更改当前目录到指定目录
        f.cwd(DIR)
    except Exception as e:
        print(e)
        exit()
    print("*** Changed dir to {0}".format(DIR))
    
    try:
        # 从FTP服务器上下载文件
        # 第一个参数是ftp命令
        # 第二个参数是回调函数
        # 此函数的意思是,执行RETR命令,下载文件到本地后,运行回调函数
        f.retrbinary('RETR {0}'.format(FILE), open(FILE, 'wb').write)
    except Exception as e:
        print(e)
        exit()
    
    # 4. 客户端从远程FTP服务器退出,结束传输
    f.quit()
    

    相关文章

      网友评论

          本文标题:Spider基础之网络编程

          本文链接:https://www.haomeiwen.com/subject/hntdlhtx.html