1.计算机网络介绍

1.1 OSI七层模型

物理层,数据链路层,网络层,传输层,会话层,表示层,应用层

 

1.2 TCP/IP协议

网络接口层,网络层,传输层,应用层

 

1.3 IP地址

对计算机而言,一个网络接口对应一个IP地址。

目前IP地址有两种:IPv4和IPv6。IPv4有2^32个不同的主机IP,IPv6将逐步取代IPv4。

IPv4有A,B,C,D,E五类地址:

A类地址范围:1.0.0.1——126.255.255.254

B类地址范围:128.0.0.1——191.255.255.254

C类地址范围:192.0.0.1——223.255.255.254

D类地址范围:224.0.0.1——239.255.255.254

E类地址范围:240.0.0.1——255.255.255.255

A,B,C三类地址用作单播地址,用于单个信源到单个目的的通信,D类地址为IP组播应用地址,E类地址为实验保留。

单播地址又有一部分是私有地址,不能与公共网络连接,私有地址为:

10.0.0.0——10.255.255.255

172.16.0.0——172.31.255.255

192.168.0.0——192.168.255.255

IPv4地址的构成:前8位,首字节,用于表示网络ID。后24位,表示主机ID。如果后24位全是0或者1的话,表示的是网络地址和广播地址。

 

1.4 子网掩码

一个组织只有2台机器,只占用两个IP,其他的IP不是浪费了吗?此时需要子网掩码。

子网掩码:用主机ID的位数来标识网络ID,从而对IP地址进行更细的分类。通常1表示网络位,0表示主机位

 

1.5 域名

主要是方便记忆,IP太难记了。而将域名和IP对应起来,需要通过DNS域名解析器。

 

2.python底层网络模块

2.1 Socket

计算机编程都离不开一个基本的组件:套接字(socket)

套接字接口以IP地址及通信端口组成套接字地址(socket Address),远程的套接字地址和本地的套接字地址完成连线后,再加上使用的协议(protocal),这个五元组(来源IP,目的IP,来源端口,目的端口,协议)作为套接字对就可以彼此交换数据了。

套接字本质是操作系统提供的一种进程间通信机制,是主机或者不同进程间可以通信。

 

2.2 socket模块

套接字格式:

#套接族,套接字类型,协议编号(默认0)
socket(family,type[,protocal])

套接字族:AF_UNIX(同一台机器),AF_INET(仅用于IPV4),AF_INET6(仅用于IPV6),AF_UNISPEC(指定主机名和服务名,并且适合任何协议族的地址)

套接字类型:SOCK_STREAM(TCP协议),SOCK_DGRAM(UDP协议),SOCK_RAW(原始套接字)

 

创建TCP socket:

sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

创建UDP socket:

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

建立socket对象后,还需要建立监听。

sock.bind(("127.0.0.1",999))
sock.listen(backlog)

backlog:最多连接数。

accept方法:等待客户请求连接

connection address= socks.accept()

 

2.3 socket对象方法

2.3.1 服务端可以使用的方法

s.bind():绑定地址到套接字

s.listen():开始TCP监听

s.accept():被动接受TCP客户端请求

 

2.3.2 客户端可以使用的方法

s.connect():主动初始化TCP服务连接

s.connect_ex():连接出错时返回错误码而不是抛出异常

 

2.3.3 公共用途方法

s.recv():接收TCP数据,以字符串形式返回

s.send():发送TCP数据,字符串发送

s.sendall():发送完整TCP数据

s.recvfrom():接收UDP数据

s.sendto():发送UDP数据

s.close():关闭套接字

s.getsockname():返回套接字地址

s.setsockopt(level,optname,value):设置套接字选项的值

s.getsockopt(level,optname,value):返回套接字选项的值

s.getpeername():返回套接字远程地址

s.getsockname():返回套接字自己地址

s.settimeout(timeout):设置超时时间

s.gettimeout():返回超时时间

s.fileno():返回套接字的文件描述符

s.setblocking(flag):是否阻塞状态

s.makefile():创建与套接字相关联的文件

 

3.TCP编程

3.1 客户端

import socket

sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(("www.baidu.com",80))
sock.send(b"GET/HTTP/1.1\r\nHOST:www.baidu.com\r\nConnection:close\r\n\r\n")

buffer = []
while True:
    content = sock.recv(1024)
    if content:
        buffer.append(content)
    else:
        break

web_content = b"".join(buffer)
print(web_content)

#分隔http协议头,保存的html文件不包含http协议头
http_header,http_content = web_content.split(b"\r\n\r\n",1)

with open("baidu.html","wb") as f:
    f.write(http_content)

3.2 服务端

import socket
import threading

def echo_server(client:socket.socket,address:tuple):
    print("欢迎来自{}:{}的新客户端".format(address[0],address[1]))
    client.send("Welcome from {}:{}\r\n".format(address[0],address[1]).encode("utf-8"))
    while True:
        content = client.recv(1024)
        if content == b"exit":
            break
        elif content:
            print(content.decode("utf-8"))
        else:
            break
    print("客户端退出")
    client.close()

sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.bind(("0.0.0.0",2018))
sock.listen(5)
print("server start !listening 0.0.0.0:2018")
while True:
    client,address = sock.accept()
    t = threading.Thread(target=echo_server,args=(client,address))
    t.start()
import socket

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",2018))
client.send("i am client!".encode("utf-8"))

server_content = client.recv(1024)
print(server_content.decode("utf-8"))

client.send(b"exit")
client.close()

 

4.UDP编程

import socket

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

server = ("127.0.0.1",2019)
sock.sendto("一起学python".encode("utf-8"),server)
sock.close()
import socket

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind(("0.0.0.0",2019))

while True:
    data,address = sock.recvfrom(1024)
    print("收到来自{}:{}的信息:".format(address[0],address[1]))
    print(data.decode("utf-8"))

 

5. urllib模块

5.1 GET请求

from urllib import request

#抓取百度
def fetch_baidu():
    http_client = request.urlopen("http://www.baidu.com")
    content = http_client.read()
    print("HTTP Status:{},{}".format(http_client.status,http_client.reason))
    print("HTTP Response headers:")
    for k,v in http_client.getheaders():
        print("{}:{}".format(k,v))

    http_client.close()
    return content.decode("utf-8")

def main():
    content = fetch_baidu()

if __name__ == "__main__":
    main()

 

5.2 post请求

import json
import pprint
from urllib import request,parse

def fetch_page():
    username = "user"
    password = "123"

    #参数需要进行url转码
    post_data = parse.urlencode([
        ("username",username),("password",password)
    ])

    #构造Request对象
    http_request = request.Request("http://httpbin.org/post")
    http_request.add_header("Refer","python")

    #data参数必须是bytes对象
    http_request.data = post_data.encode("utf-8")

    with request.urlopen(http_request) as http_response:
        content = http_response.read()
        result = json.loads(content.decode("utf-8"))
        pprint.pprint(result)

def main():
    fetch_page()

if __name__ == "__main__":
    main()

 

6.requests模块介绍

首先需要导入:

conda install requests
import requests

r = requests.get("http://httpbin.org/get")
print(r.text)

#post参数只需要传递字典即可,不需要手动执行
r = requests.post('http://httpbin.org/post',data={'key':'value'})
print(r.text)

r = requests.put('http://httpbin.org/put',data={'key':'value'})
print(r.text)

r = requests.delete('http://httpbin.org/delete')
print(r.text)

r = requests.head('http://httpbin.org/get')
print(r.text)

r = requests.options('http://httpbin.org/get')
print(r.text)