爬虫基础-计算机网络协议

一个数据的传输
image.png
这些设备的数据转发是通过协议来完成的,整个互联网可以说是完全由网络协议来维持的
不同的协议分工不同,比如ip协议确保了ip寻址,tcp协议确保了数据完整性

IP地址和URL

ip地址
整个网络传输可以比作快递,数据就是快递包裹
ip地址就是门牌号
URL
url(uniform resource locator)- 统一资源定位符,每一个url指向一个独特的资源,可以是一个html页面、一个css文档、一个图片、文件、js文件等
URL协议
image.png
常用协议:http、https、file、ftp
域名:可以看做说ip地址的别名,此次也可以直接填写ip地址

七层网络协议

image.png
image.png
image.png

TCP/IP协议

TCP协议
Tcp(传输控制协议)是一种面向连接、可可靠的基于字节流的传输层协议
理解:
tcp协议负责把需要传输的数据分解成一定长度的“片段”。
IP协议
Ip协议用于将多个数据包交换网络连接起来,它在源地址和目的地址之间传输数据包
理解
ip协议负责将数据“片段”贴上标签,成为数据包,标签包括“源ip地址”和“目标ip地址”。这些标签将决定数据传输的路径。Ip协议负责传送的道路被称为“路由功能”
路由器
路由器,是连接互联网各局域网、广域网的设备,他会根据信道的情况自动选择和设置路由,以最佳路径,按前后顺序发送数据
理解:
每个节点上的路由器都记录着与自己相邻的路由器地址,并形成一个表格-路由表,路由表是一个动态数据库,并在网络活动中不断更新。
数据包达到一个路由器后,该路由器会根据数据包的地址信息,查询路由表,然后选择一个最佳的路径发送数据包。

TCP是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务器的内存里保存的一份关于对方的信息,如ip地址、端口号等。
TCP可以看成是一种字节流,它会处理IP层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。
TCP提供了一种可靠、面向连接、字节流、传输层的服务,采用三次握手建立一个连接。采用4次挥手来关闭一个连接。

Socket

Socket可以用英文概念理解:插座
电力公司给你家送电是通过电线,但是电送到你家还不够,家里还得有个插座(socket),这样你才能用上电,插座上有火线、地线和中线。 可以理解为ip地址/端口等。
Socket本身并不是一个协议,是一个套接字,操作系统为了方便大家直接使用tcp协议而存在的一个抽象层,它把复杂的tcp/ip协议隐藏在接口后面。
image.png
image.png
socket_server

#socket服务端
import socket
import threading
server = socket.socket()
#绑定到0.0.0.0:8000端口上
server.bind(('0.0.0.0', 8000))
server.listen()

def handle_sock(sock, addr):
    while True:
        # recv方法是阻塞的
        tmp_data = sock.recv(1024)
        print(tmp_data.decode("utf8"))
        input_data = input()
        sock.send(input_data.encode("utf8"))

#获取客户端连接并启动线程去处理
while True:
    # 阻塞等待连接
    sock, addr = server.accept()

    #启动一个线程去处理新的用户连接
    client_thread = threading.Thread(target=handle_sock, args=(sock, addr))
    client_thread.start()


#体验到直接获取原始数据,裸数据




    # if tmp_data:
    #     data += tmp_data.decode("utf8")
    #     if tmp_data.decode("utf8").endswith("#"):
    #         break
    # else:
    #     break;

# print(data)
# sock.close()

socket_client

#socket客户端
import socket
client = socket.socket()
client.connect(('127.0.0.1', 8000))

# client.send(b"bobby")
#当输出完成以后 以#结尾就代码提交完成
# server_data = client.recv(1024)
# print("server response: {}".format(server_data.decode("utf8")))
while True:
    input_data = input()
    client.send(input_data.encode("utf8"))
    server_data = client.recv(1024)
    print("server response: {}".format(server_data.decode("utf8")))

# client.close()

模拟qq服务器和客户端
server

#qq服务器
#1. 转发消息
#2. 处理登录
#3. 处理退出
#4. 维护历史消息, 维护在线用户和维护用户的连接
import socket
import json
from collections import defaultdict
import threading

#1. 维护用户连接
online_users = defaultdict(dict)

#2. 维护用户的历史消息
user_msgs = defaultdict(list)

server = socket.socket()

#绑定ip
server.bind(("0.0.0.0", 8000))
server.listen()

def handle_sock(sock, addr):
    while True:
        data = sock.recv(1024)
        json_data = json.loads(data.decode("utf8"))
        action = json_data.get("action", "")
        if action == "login":
            online_users[json_data["user"]] = sock
            sock.send("登录成功!".encode("utf8"))
        elif action == "list_user":
            #获取当前在线用户
            all_users = [user for user, sock in online_users.items()]
            sock.send(json.dumps(all_users).encode("utf8"))
        elif action == "history_msg":
            sock.send(json.dumps(user_msgs.get(json_data["user"], [])).encode("utf8"))
        elif action == "send_msg":
            if json_data["to"] in online_users:
                online_users[json_data["to"]].send(json.dumps(json_data).encode("utf8"))
            user_msgs[json_data["to"]].append(json_data)
        elif action == "exit":
            del online_users[json_data["user"]]
            sock.send("退出成功!".encode("utf8"))

while True:
    #阻塞等待连接
    sock, addr = server.accept()
    #启动一个线程去处理新的用户连接
    client_thread = threading.Thread(target=handle_sock, args=(sock, addr))
    client_thread.start()

#1. 多线程去处理每个用户连接,防止主线程阻塞住
#2. 自定义了消息协议并且自己完成了消息协议的解析

client

#qq客户端
import socket
import json
import threading

client = socket.socket()
client.connect(("127.0.0.1", 8000))

user = "bobby1"

#1. 登录
login_template = {
    "action":"login",
    "user":user
}
client.send(json.dumps(login_template).encode("utf8"))
res = client.recv(1024)
print(res.decode("utf8"))

#2. 获取在线用户
get_user_template = {
    "action":"list_user"
}
client.send(json.dumps(get_user_template).encode("utf8"))
res = client.recv(1024)
print("当前在线用户:{}".format(res.decode("utf8")))

#2. 获取历史消息
offline_msg_template = {
    "action":"history_msg",
    "user":user
}
client.send(json.dumps(offline_msg_template).encode("utf8"))
res = client.recv(1024)
print("历史消息:{}".format(res.decode("utf8")))

exit = False
def hanle_receive():
    #处理接收请求
    while True:
        if not exit:
            try:
                res = client.recv(1024)
            except:
                break
            res = res.decode("utf8")
            try:
                res_json = json.loads(res)
                msg = res_json["data"]
                from_user = res_json["from"]
                print("")
                print("收到来自({})的消息: {}".format(from_user, msg))
            except:
                print("")
                print(res)
        else:
            break

def handle_send():
    while True:
        #1. 随时可以发送消息
        #2. 有新消息随时能接收到
        op_type = input("请输入你要进行的操作: 1. 发送消息, 2. 退出, 3. 获取在线用户")
        if op_type not in ["1","2","3"]:
            print("不支持该操作!!!")
            op_type = input("请输入你要进行的操作: 1. 发送消息, 2. 退出, 3. 获取在线用户")
        elif op_type == "1":
            to_user = input("请输入你要发送的用户:")
            msg = input("请输入你要发送的消息")
            send_data_template = {
                "action": "send_msg",
                "to": to_user,
                "from": user,
                "data": msg
            }
            client.send(json.dumps(send_data_template).encode("utf8"))
        elif op_type == "2":
            exit_template = {
                "action": "exit",
                "user": user
            }
            client.send(json.dumps(exit_template).encode("utf8"))
            exit = True
            client.close()
            break
        elif op_type == "3":
            get_user_template = {
                "action": "list_user"
            }
            client.send(json.dumps(get_user_template).encode("utf8"))

if __name__ == "__main__":
    send_thread = threading.Thread(target=handle_send)
    receive_thread = threading.Thread(target=hanle_receive)
    send_thread.start()
    receive_thread.start()





#qq客户端
import socket
import json
import threading

client = socket.socket()
client.connect(("127.0.0.1", 8000))

user = "bobby2"

#1. 登录
login_template = {
    "action":"login",
    "user":user
}
client.send(json.dumps(login_template).encode("utf8"))
res = client.recv(1024)
print(res.decode("utf8"))

#2. 获取在线用户
get_user_template = {
    "action":"list_user"
}
client.send(json.dumps(get_user_template).encode("utf8"))
res = client.recv(1024)
print("当前在线用户:{}".format(res.decode("utf8")))

#2. 获取历史消息
offline_msg_template = {
    "action":"history_msg",
    "user":user
}
client.send(json.dumps(offline_msg_template).encode("utf8"))
res = client.recv(1024)
print("历史消息:{}".format(res.decode("utf8")))

exit = False
def hanle_receive():
    #处理接收请求
    while True:
        if not exit:
            try:
                res = client.recv(1024)
            except:
                break
            res = res.decode("utf8")
            try:
                res_json = json.loads(res)
                msg = res_json["data"]
                from_user = res_json["from"]
                print("")
                print("收到来自({})的消息: {}".format(from_user, msg))
            except:
                print("")
                print(res)
        else:
            break

def handle_send():
    while True:
        #1. 随时可以发送消息
        #2. 有新消息随时能接收到
        op_type = input("请输入你要进行的操作: 1. 发送消息, 2. 退出, 3. 获取在线用户")
        if op_type not in ["1","2","3"]:
            print("不支持该操作!!!")
            op_type = input("请输入你要进行的操作: 1. 发送消息, 2. 退出, 3. 获取在线用户")
        elif op_type == "1":
            to_user = input("请输入你要发送的用户:")
            msg = input("请输入你要发送的消息")
            send_data_template = {
                "action": "send_msg",
                "to": to_user,
                "from": user,
                "data": msg
            }
            client.send(json.dumps(send_data_template).encode("utf8"))
        elif op_type == "2":
            exit_template = {
                "action": "exit",
                "user": user
            }
            client.send(json.dumps(exit_template).encode("utf8"))
            exit = True
            client.close()
            break
        elif op_type == "3":
            get_user_template = {
                "action": "list_user"
            }
            client.send(json.dumps(get_user_template).encode("utf8"))

if __name__ == "__main__":
    send_thread = threading.Thread(target=handle_send)
    receive_thread = threading.Thread(target=hanle_receive)
    send_thread.start()
    receive_thread.start()





http协议

HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写。它的发展是万维网协会(World Wide Web Consortium)和Internet工作小组IETF(Internet Engineering Task Force)合作的结果,(他们)最终发布了一系列的RFC。http是应用层协议。
HTTP协议永远都是客户端发起请求,服务器回送响应,这样就限制了使用HTTP协议,无法实现在客户端没有发起请求的时候,服务器将消息推送给客户端。HTTP协议是一个无状态的协议,同一个客户端的这次请求和上次请求是没有对应关系。http协议是单向的。
HTTP 协议是个纯文本的协议,:这意味着我们直接传递纯文本就可以了换句话说,一个 Web 服务器其实就是根据约定好的方法生成对应的 HTTP 消息内容然后传输给对方。

http协议格式

简单快速:只需要传递请求方法和路径。
灵活:http可以传递任意类型的数据对象。通过content-type指定
无连接:无连接意味着每次连接处理一个请求,服务器返回之后断开连接,节省传输时间和服务器压力。
无状态:无状态是指协议对于事物处理没有记忆能力,需要通过cookie和session来加以区别。
支持B/S和C/S模式
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/355814.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023年度总结——忙忙碌碌,终有归章

思来想去,还是决定写一篇年终总结,一来算是对23年的一年的回顾,二来是对24年的展望。记得22年也写过一篇年度总结,题目是《2022年度总结——一切都在慢慢变好》。今年,我想起的题目是《2023年度总结——忙忙碌碌&#…

在Temu跨境电商平台上,如何快速出单?

随着越来越多的商家选择入驻Temu跨境电商平台,一旦入驻申请通过,商家就可以开始上架商品并等待订单的产生。然而,很多新手跨境电商卖家都面临一个共同的问题,那就是:Temu出单快吗?Temu上架多久能出单&#…

STM32CubeMX教程27 SDIO - 读写SD卡

目录 1、准备材料 2、实验目标 3、轮询方式读取SD卡流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.0、工程基本配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.0、配置Project Manager页面 3.2.1、外设初始化调用流程 3.2.2、外设中断调用流…

激光雷达,角力「降本增效」

高工智能汽车研究院最新发布的数据显示,2023年1-11月,中国市场(不含进出口)乘用车前装标配激光雷达搭载量为46.48万颗,同比增长372.35%,继续保持高增长态势。 随着激光雷达在中国市场完成规模化上量的节点&…

Promethues是什么?

什么是Prometheus? Prometheus是一个开源的系统监控以及报警系统。整和zabbix的功能,系统,网络,设备。 promethues可以兼容网络、设备、容器监控、告警系统。因为和k8s是一个项目基金开发的产品,天生就匹配k8s的原生…

离线安装nginx_银河麒麟系统_nginx报错_503_500 Internal Server Error----nginx工作笔记007

如果报这个错误,意思就是,对于nginx.conf文件中指定的,文件夹没有权限 那么这个是去给对应的文件夹赋权限: chmod 777 /opt/module/test_web 就可以了,然后再去访问就不会报错了,还有 503的错误都可以这样解决 然后关于离线安装nginx,尝试了一下如果把之前安装过的nginx,直接…

AI-数学-高中-10-2-分数指数幂计算

原作者视频:初等函数】2分数指数幂的计算(基础)_哔哩哔哩_bilibili 方法1: 方法2:

Matlab绘图技巧-NAN元素绘图出现锯齿状解决办法

Matlab绘图技巧-NAN元素绘图出现锯齿状解决办法 想必有很多同学遇到绘制3维曲面热力图,有一些数据是nan,绘制出来的图会出现锯齿状:如下图:    如果用matlab直接绘制带nan的矩阵的话,则会像上图一样,当然…

【教程】iOS 手机抓包工具介绍及教程

📱 最近又发现APP Store一款宝藏软件,克魔助手抓包工具,app刚上架,功能不断迭代中,目前18软妹币实惠价可享受终身版!现在是下手的最好时机。 引言 移动端开发中,抓包工具已成为必备的工具之一…

电脑文件夹怎么加密保护?文件夹加密软件推荐

电脑文件夹可以帮助我们管理各种文件,而文件夹加密则可以有效地保护数据安全。那么,电脑文件夹该怎么加密保护呢?下面我们就一起来了解一下。 超大文件夹加密 电脑中会有一些存放着视频、图纸等大文件的文件夹。这些文件夹体积庞大&#xff…

面试官:Mysql中EXISTS与IN的使用有哪些差异

在数据库查询优化中,查询效率直接关系到应用程序性能。其中,IN和EXISTS是两种常见的子查询操作符,广泛应用于SQL查询语句,但它们在执行效率上有所不同。 本文深入探讨IN和EXISTS的工作原理,以及在何种情境下选择更为合…

QGIS使用地理配准将3857坐标系转成上海城建坐标

控制点格式 如 mapX mapY sourceX sourceY enable dX dY residual -58653 70641 13452659.39 3746386.025 1 0 0 0 -58653 65641 13452693.09 3740477.283 1 0 0 0 ......保存为.points格式 图层预处理 图层投影为3857坐标系 地理配准 1. 打开图层-地理配准 工具 2. 导入…

ATAC-seq发篇测序文章就结束了吗?看如何利用ATAC-seq数据为后续关键基因的转录调控研究提供重要依据

染色质可及性(Chromatin Accessibility)是染色质的一种特性,为转录因子结合靶基因提供了空间。转座酶可及染色质测序分析(ATAC-seq)是常见的研究染色质可及性的方法,ATAC-seq联合RNA-seq是一种新的研究思路…

day10 Javaweb

第一章 WEB概述 1.1 JAVAWEB简介 用Java技术来解决相关web互联网领域的技术栈.使用JAVAEE技术体系开发企业级互联网项目. 项目规模和架构模式与JAVASE阶段有着很大的差别. 在互联网项目下,首先需要明白客户端和服务器的概念 客户端 :与用户进行交互,用于接收用户的…

解决ubuntu 在VMware Workstation Pro下显示不完整的问题

步骤一 ctrlaltT 打开终端,输入: xrandr -s 1920x1080如果报错就输入xrandr,从里面选择适合的分辨率 注意是字母x不是乘号 步骤二 按win键,在搜索框搜索resolution更改显示器分辨率: 选择与电脑相同的分辨率,点击…

(二十一)Flask之上下文管理第二篇(细细扣一遍源码)

每篇前言: 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者 🔥🔥本文已收录于Flask框架从入门到实战专栏:《Flask框架从入…

【MISRA C 2012】Rule 5.6 类型定义名称应该是唯一的标识符

1. 规则1.1 原文1.2 分类 2. 关键描述3. Example4. 代码实例 1. 规则 1.1 原文 1.2 分类 规则5.6:类型定义名称应该是唯一的标识符 Required要求类规范。 2. 关键描述 typedef名称在所有名称空间和翻译单元中应该是唯一的。只有当类型定义在头文件中并且该头文件…

HiveSQL题——窗口函数(lag/lead)

目录 一、窗口函数的知识点 1.1 窗户函数的定义 1.2 窗户函数的语法 1.3 前后函数:lag/lead 二、实际案例 2.1 股票的波峰波谷 0 问题描述 1 数据准备 2 数据分析 3 小结 2.2 前后列转换(面试题) 0 问题描述 1 数据准备 2 数据分析 3 小结…

【C语言】linux内核ipoib模块 - ipoib_netdev_ops_pf结构

一、ipoib_netdev_ops_pf结构 static const struct net_device_ops ipoib_netdev_ops_pf {.ndo_init ipoib_ndo_init,.ndo_uninit ipoib_ndo_uninit,.ndo_open ipoib_open,.ndo_stop ipoib_stop,.ndo_change_mtu ipoib_change_mtu,.ndo_…

将word中插入的zotero文献转为latex引用样式

在word中,可以使用zotero插件插入和管理参考文献。 例如: 若需要将这段内容移植到latex,就需要将对应的引用编号用\cite{}替换。手动替换非常麻烦且容易出错。要实现自动转换,可在zotero中定制一种新的引文格式,自动将…