zoukankan      html  css  js  c++  java
  • 《Python网络编程基础》第一章 读书笔记。

    首先这本书还时非常好的,书中的示例代码都在更新,我上的代码都是他官方github上面下载的最新代码。

    第一章 客户端/服务器网络编程简介

    获取经纬度,首先是通过三方包实现,很方便。

    from geopy.geocoders import Nominatim
    
    if __name__ == '__main__':
        address = '207 N. Defiance St, Archbold, OH'
        user_agent = 'Foundations of Python Network Programming example search1.py'
        # user_agent = 'sidian'
        location = Nominatim(user_agent=user_agent).geocode(address)
        print(location.latitude, location.longitude)
    

     输出

    41.5427511 -84.3067015

    1.2应用层

    书中通过调用requests的三方包实现。

    import requests
    
    def geocode(address):
        base = 'https://nominatim.openstreetmap.org/search'
        parameters = {'q': address, 'format': 'json'}
        user_agent = 'Foundations of Python Network Programming example search2.py'
        headers = {'User-Agent': user_agent}
        # 携带了参数与头部信息
        response = requests.get(base, params=parameters, headers=headers)
        reply = response.json()
        print(reply[0]['lat'], reply[0]['lon'])
    
    if __name__ == '__main__':
        geocode('207 N. Defiance St, Archbold, OH')
    

     输出与上面一样

    1.3协议的使用。

    书中主要介绍了http协议在应用层的使用很宽广。

    示例代码

    import http.client
    import json
    from urllib.parse import quote_plus
    
    base = '/search'
    
    def geocode(address):
        # 这里传入的headers与返回的response都是二进制文件。
        path = '{}?q={}&format=json'.format(base, quote_plus(address))
        user_agent = b'Foundations of Python Network Programming example search3.py'
        headers = {b'User-Agent': user_agent}
        # 这个定义了一个http协议的对象,参数只需要域名就可以了,因为协议已经写在方法里面了
        connection = http.client.HTTPSConnection('nominatim.openstreetmap.org')
        connection.request('GET', path, None, headers)
        # 读取返回二进制数据
        rawreply = connection.getresponse().read()
        reply = json.loads(rawreply.decode('utf-8'))
        print(reply[0]['lat'], reply[0]['lon'])
    
    if __name__ == '__main__':
        geocode('207 N. Defiance St, Archbold, OH')
    

     可能是网络原因,没跑通。

    1.4 一个原始的网络会话

    书中已经用了一个简单的示例完成一个socket发送请求的情况。

    #!/usr/bin/env python3
    # Foundations of Python Network Programming, Third Edition
    # https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter01/search4.py
    
    # (The Google API originally used in this example now requires API keys,
    #  so here's an alternative that calls openstreetmap.org.)
    
    import socket
    import ssl
    from urllib.parse import quote_plus
    
    #请求头所有信息
    request_text = """
    GET /search?q={}&format=json HTTP/1.1
    
    Host: nominatim.openstreetmap.org
    
    User-Agent: Foundations of Python Network Programming example search4.py
    
    Connection: close
    
    
    
    """
    
    def geocode(address):
        # 打开一个socket
        unencrypted_sock = socket.socket()
        # 连接socket,建立与服务器的三次握手
        unencrypted_sock.connect(('nominatim.openstreetmap.org', 443))
        # 建立ssl通道,进行通道加密
        sock = ssl.wrap_socket(unencrypted_sock)
        '''
        也可以直接加密通道
        sock = ssl.wrap_socket(unencrypted_sock)
        加密通道与服务器进行连接,认证。
        sock.connect(('nominatim.openstreetmap.org', 443))
        '''
        # 格式化请求头信息
        request = request_text.format(quote_plus(address))
        # 编码成字节码发送
        sock.sendall(request.encode('ascii'))
        # 定义空字节码
        raw_reply = b''
        while True:
            # 接收返回的信息,设定块大小
            more = sock.recv(4096)
            if not more:
                break
            raw_reply += more
        # 所有头信息,body都会返回
        print(raw_reply.decode('utf-8'))
    
    if __name__ == '__main__':
        geocode('207 N. Defiance St, Archbold, OH')
    

      输出

    HTTP/1.1 200 OK
    Server: nginx
    Date: Thu, 03 Dec 2020 08:27:37 GMT
    Content-Type: application/json; charset=UTF-8
    Transfer-Encoding: chunked
    Connection: close
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Methods: OPTIONS,GET

    1a7
    [{"place_id":174011511,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"way","osm_id":379245933,"boundingbox":["41.5427373","41.5433134","-84.3067095","-84.3067012"],"lat":"41.5427511","lon":"-84.3067015","display_name":"North Defiance Street, Burlington, Archbold, Fulton County, Ohio, 43502, United States of America","class":"highway","type":"secondary","importance":0.61}]
    0

    上面显式了一个标准的response的输出情况。

    1.5层层深入

     略

    1.6编码与解码

    if __name__ == '__main__':
        # Translating from the outside world of bytes to Unicode characters.
        input_bytes = b'xffxfe4x001x003x00 x00ix00sx00 x00ix00nx00.x00'
        # 通过解码输出文字,这个作者真的用心良苦,用utf-16解码,让字节码与原丝字符串完全不一样
        input_characters = input_bytes.decode('utf-16')
        # 通过repr输出更加厉害
        print(repr(input_characters))
    
        # Translating characters back into bytes before sending them.
        output_characters = 'We copy you down, Eagle.
    '
        # 编码成字节码
        output_bytes = output_characters.encode('utf-8')
        # 写入文件二进制格式,打开的时候就可以直接显示字符串,因为操作系统用软件打开文件,会自动帮你解码
        with open('eagle.txt', 'wb') as f:
            f.write(output_bytes)
    

      上面是示例代码,跟书中的完全不一样,写的真心的不错。

    实例代码中通过直接向二进制文件写入字节码,后续也能通过打开,更好的解释了文件内保存的都是二进制,我们看到的只不过是已经解码以后的字符串信息。

    1.7 网际协议

    网际协议(IP)是为全世界通过互联网连接的计算机赋予统一地址系统的一种机制,它使得数据包能够从互联网的一端发送至另一端。

    也就使所谓的IP协议,但一般我们很少去接触IP协议。我们接触最多到传输层。

    1.8 IP地址

    示例代码

    import socket
    
    if __name__ == '__main__':
        hostname = 'baidu.com'
        # 获取域名的地址
        addr = socket.gethostbyname(hostname)
        print('The IP address of {} is {}'.format(hostname, addr))
    

      通过socket.gethostbyname的方法来获得域名对应的IP地址。

    现在的IP4用的4个字节,后面切换IP6的话,就是16字节。

    一些特殊的IP地址段

    127.*.*.*:以127开头的IP地址是特殊的预留地址段,这一地址段由机器上运行的本地应用程序使用

    127.0.0.1 == localhost 对应就是本机。

     

    10.*.*.*

    172.16-31.*.*

    193.168.*.*

    上面这三个IP地址段为私有网络(Private subnet)预留的。构建内网的时候,可以拿来使用。

    1.9路由

    路由一般也不用我们操心,自己操作系统或者路由器会根据路由表对数据进行发送。

    是否是同一个子网可以通过ip与掩码来提现

    192.168.1.9/24,就是前面24位相同就可以了,后面8位有256种可能,一个给网关,一个.0表示子网名,255记得应该是广播地址。

    1.10数据包分组

     学的也模模糊糊,就知道了以太网只支持1500B的数据包,一般UDP不设置DF(Don't Fragment)标记,tcp设置。

    很多概念性的东西,我学的还是比较累的。

  • 相关阅读:
    svn命令行使用积累
    linux下编译出现tmp空间不足解决办法
    secure CRT the remote system refused the connection 解决办法
    Makefile 中符合的使用
    函数指针作为某个函数的参数及定义函数指针(回调函数)
    C语言指针变量作为函数参数
    虚拟机下安装ubuntu后root密码登录失败的问题
    管理者需要知道的十大经典理论
    System V 与 POSIX
    带你吃透RTMP
  • 原文地址:https://www.cnblogs.com/sidianok/p/13934460.html
Copyright © 2011-2022 走看看