第7章 网络编程考察点

网络协议TCP/UDP/HTTP 常考题

浏览器输入一个url中间经历的过程

  • 中间涉及到了哪些过程

  • 包含哪些网络协议

  • 每个协议都干了什么?
    • DNS查询->TCP握手->HTTP请求->反向代理Nginx->uwsgi/gunicom->web app响应->TCP挥手

TCP三次握手过程

TCP三次握手, 状态转换。用wireshark抓包更直观

TCP四次挥手过程

TCP四次挥手,状态装换

client state C S server state

TCP/UDP的区别

TCP vs UDP

  • 面向连接,可靠的,基于字节流

  • 无连接,不可靠,面向报文

总结

  • 记忆内容多,间隔记忆,多次重复,检索学习,穿插练习

  • 费曼学习技巧,用简单的语言去教别人,检验自己是否真正的懂

  • 如果解释过程中遇到障碍,重新学习知识点(分治)

HTTP协议常考题

HTTP请求的组成

HTTP协议由哪些部分组成?

  • 状态行

  • 请求头

  • 消息主体

HTTP响应的组成

HTTP协议由哪些部分组成?

  • 状态行

  • 响应头

  • 响应正文

HTTP常见状态码

  • 1**信息,服务器收到请求,需要请求者继续执行操作

  • 2**成功,操作被成功接受并处理

  • 3**重定向,需要进一步操作完成请求

  • 4**客户端错误,请求有语法错误或者无法完成请求

  • 5**服务端错误,服务器在处理请求的过程中发生错误

  • 牢记常见状态码的含义(220, 301, 302, 400, 403, 500等)

HTTP GET/POST的区别?

​ 常见的HTTP方法: GET/POST/PUT/DELETE

​ GET 获取 POST 创建 PUT 更新 DELETE 删除

​ Restful 语义上一个是获取,一个是创建

​ GET是幂等的,POST非幂等

​ GET请求参数放到url(明文),长度限制,POST放到请求体,更安全

什么是幂等性

​ 哪些HTTP 方法是幂等的

​ 幂等方法是无论调用多少次都得到相同结果的HTTP方法

​ eg: a=4是幂等的,但是 a += 4 是非幂等

​ 幂等的方法客户端可以安全地重发请求

什么是HTTP长连接

是TCP的应用层

HTTP persistent connection, HTTP 1.1

​ 短连接: 建立连接...数据传输...关闭连接(连接的建立和关闭开销大)

​ 长连接: Connection: Keep-alive 保持TCP连接不断开

如何区分不同HTTP请求?

Content-Length | Transfer-Encoding: chunked

  • 客户端告诉服务端发送的HTTP请求有多长?
    • Content-Length首部告诉浏览器报文中实体主体的大小

cookie和session的区别?

HTTP是无状态的,如何识别用户呢?

  • Session 一般是服务器生成之后给客户端(通过url参数或cookie)

  • Cookie 是实现session的一种机制,通过HTTP cookie字段实现

  • Session通过在服务器保存sessionid识别用户,cookie存储在客户端

总结:

  • 请求和响应的组成

  • 常用HTTP方法和幂等性

  • 长连接,session和cookie

网络编程常考题

socket编程对于学习框架原理比较重要

TCP/UDP socket编程,HTTP编程

  • 了解TCP编程的原理

  • 了解UDP编程的原理

  • 了解如何发送HTTP请求

TCP socket编程原理?

  • 如何使用socket模块

  • 如何建立TCP socket 客户端和服务端

  • 客户端和服务端之间的通信

# !< server.py
import socket
import time

s = socket.socket()
s.bind('', 8888)
s.listen()

while True:
    client, addr = s.accept()   #return conn, addr
    print(client)
    timestr = time.ctime(time.time()) + '\r\n'
    client.send(timestr.encode())   #send 参数 encode
    client.close()
# !< client.py

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8888))
s.sendall(b'Hello World')
data = s.recv(1024)
print(data.decode())
s.close()

使用socket发送HTTP请求

如何使用socket发送HTTP请求

  • 使用socket接口发送HTTP请求

  • HTTP建立在TCP基础之上

  • HTTP是基于文本的协议

import socket

s = socket.socket()
s.connect(('www.baidu.com', 80))

http = b"GET /HTTP/1.1\r\nHost: www.baidu.com\r\n\r\n"
s.sendall(http)
buf = s.recv(1024)
print(buf)
s.close()
#接受完整的响应

IO多路复用常考题

五种IO模型

Unix网络编程提到的5种网络模型

  • Blocking IO

  • Nonblocking IO

  • IO multiplexing

  • Signal Driven IO

  • Asynchronous IO

两种不常用,一般使用IO多路复用比较多

如何提升服务器的并发能力呢?

  • 多线程模型,创建新的线程处理请求
  • 多进程模型,创建新的进程处理请求
  • 线程/进程创建开销比较大,可以用线程池方式解决

  • 线程和进程比较占用资源,难以同时创建太多
  • IO多路复用,实现单进程同时处理多个socket请求

什么是IO多路复用?

操作系统提供的同时监听多个socket的机制

​ 为了实现高并发需要一种机制并发处理多个socket

​ linux常见的是select/poll/epoll

​ 可以使用单线程单进程处理多个socket

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)

py如何实现IO多路复用?

py封装操作系统的IO多路复用

  • py的IO多路复用基于操作系统实现(select/poll/epoll)

  • py2 select模块

  • py3 selectors模块

selectors模块

​ 事件类型: EVENT_READ, EVENT_WRITE

​ DefaultSelector: 自动根据平台选取合适的IO模型

​ register(fileobj, events, data = None)

​ unregister(fileobj)

​ modify(fileobj, events, data=None)

​ select(timeout=None): returns[(key, events)]

​ close()

py 并发网络库常考题

Tornado/Gevent

用过哪些并发网络库?

​ Tornado vs Gevent vs Asyncio

​ Tornado 并发网络库和同时也是一个web微框架

​ Gevent 绿色线程(greenlet)实现并发, 猴子补丁修改内置socket

​ Asyncio Python3 内置的并发网络库,基于原生协程

Tornado框架

​ Tornado适用于微服务,实现Restful接口

​ 底层基于linux多路复用

​ 可以通过协程或者回调实现异步编程

​ 相应的异步框架比如ORM不完善

import tornado.ioloop
import tornado.web

from tornado.httpclient import AsyncHTTPClient

class APIHandler(tornado.web.Requestandler):
    async def get(self):
        url = 'http://httpbin.org/get'
        http_client = AsyncHTTPClient()
        resp = http_client.fetch(url)
        print(resp.body)
        return resp.body

def make_app():
    return tornado.web_Application([
        (r"/api", APIHandler)
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()

Gevent

高性能的并发网络库

​ 基于轻量级绿色线程(greenlet)实现并发

​ 需要注意monkey patch, gevent修改了内置的socket改为非阻塞

​ 配合gunicorn 和 gevent 部署作为wsgi server

import gevent.monkey
gevent.monkey.patch_all()   #修改内置的一些库非阻塞

import gevent
import requests

def fetch():
    url = 'http://httpbin.org/get'
    resp = request.get(url)
    print(len(resp.text), i)

def asynchronous():
    threads = []
    for i in range(1, 10):
        threads.append(gevent.spawn(fetch, i))
    gevent.joinall(threads)

print('Asynchronous: ')
asynchronous()

Asyncio

基于协程实现的内置并发网络库

py3 引入到内置库,协程 + 事件循环

基于Aiohttp 可以实现一些小的服务

基于aiohttp并发请求

import asyncio
from aiohttp import Client Session #pip install aiohttp

async def fetch(url, session):
    async with session.get(url) as response:
        return await response.read()

async def run(r=10):
    url = "http://httpbin.org/get"
    tasks = []

async with ClientSession() as Session:
    for i in range(r):
        task = asyncio.ensure_future(fetch(url, session))
        tasks.append(task)
    responses = await asyncio.gather(*tasks)
    for resp_body in responses:
        print(len(resp_body))

loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run())
loop.run_until_complete(future)

编写一个异步爬虫类

使用py的gevent或者asyncio编写一个异步爬虫类

​ 该类可以传入需要抓取的网址列表

​ 该类可以通过继承的方式提供一个处理response的方法

猜你喜欢

转载自www.cnblogs.com/xuzhaoping/p/11616802.html