s21day30 python笔记
程序员文章站
2022-04-19 12:42:05
s21day30 python笔记 一、内容回顾及补充 1. 简述三次握手和四次挥手 三次握手 accept接受过程中等待客户端的连接 connect客户端发起一个syn链接请求 如果得到了server端响应ack的同时还会再收到一个由server端发来的syc链接请求 client端进行回复ack ......
s21day30 python笔记
一、内容回顾及补充
- 简述三次握手和四次挥手
- 三次握手
- accept接受过程中等待客户端的连接
- connect客户端发起一个syn链接请求
- 如果得到了server端响应ack的同时还会再收到一个由server端发来的syc链接请求
- client端进行回复ack之后,就建立起了一个tcp协议的链接
- 三次握手的过程再代码中是由accept和connect共同完成的,具体的细节再socket中没有体现出来
- 四次挥手
- server和client端对应的在代码中都有close方法
- 每一端发起的close操作都是一次fin的断开请求,得到'断开确认ack'之后,就可以结束一端的数据发送
- 如果两端都发起close,那么就是两次请求和两次回复,一共是四次操作
- 可以结束两端的数据发送,表示链接断开了
- 三次握手
- tcp协议和udp协议的特点
- tcp协议:是一个面向连接的,流式的,可靠的,慢的,全双工通信
- 邮件 文件 http web
- udp协议:是一个面向数据报的,无连接的,不可靠,快的,能完成一对一、一对多、多对一、多对多的高效通讯协议
- 即时聊天工具 视频的在线观看
- tcp协议:是一个面向连接的,流式的,可靠的,慢的,全双工通信
二、黏包现象
- 定义:同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种现象就是黏包
- 黏包成因:只有tcp有黏包现象,udp永远不会黏包
- tcp协议中的数据传递
- tcp协议的拆包机制
- 面向流的通信特点
- tcp协议中的数据传递
- 会发生黏包的两种情况:
- 情况一 发送方的缓存机制
- 情况二 接收方的缓存机制
- 总结:
- 黏包现象只发生在tcp协议中
- 从表面上看,黏包问题主要是因为发送方和接收方的缓存机制、tcp协议面向流通信的特点
- 实际上,主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的
- tcp协议的黏包现象
- 什么是黏包现象
- 发生在发送端的黏包
- 由于两个数据的发送时间间隔短+数据的长度小
- 所以由tcp协议的优化机制将两条信息作为一条信息发送出去了
- 为了减少tcp协议中的“确认收到”的网络延迟时间
- 发生再接收端的黏包
- 由于tcp协议中所传输的数据无边界,所以来不及接收的多条
- 数据会在接收放的内核的缓存端黏在一起
- 本质: 接收信息的边界不清晰
- 发生在发送端的黏包
- 解决黏包问题
- 自定义协议1
- 首先发送报头,报头长度4个字节,内容是即将发送的报文的字节长度
- struct模块 pack 能够把所有的数字都固定的转换成4字节
- 再发送报文
- 首先发送报头,报头长度4个字节,内容是即将发送的报文的字节长度
- 自定义协议2
- 我们专门用来做文件发送的协议
- 先发送报头字典的字节长度,再发送字典(字典中包含文件的名字、大小),再发送文件的内容
- 自定义协议1
- 什么是黏包现象
三、验证客户端的合法性
-
客户端是提供给 用户用的 —— 登陆验证
- 你的用户 就能看到你的client源码了,不需要自己写客户端了
-
客户端是提供给 机器使用的
# 方式一: # server.py import os import hashlib import socket def get_md5(secret_key,randseq): md5 = hashlib.md5(secret_key) md5.update(randseq) res = md5.hexdigest() return res def chat(conn): while true: msg = conn.recv(1024).decode('utf-8') print(msg) conn.send(msg.upper().encode('utf-8')) sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() secret_key = b'alexsb' while true: conn,addr = sk.accept() randseq = os.urandom(32) conn.send(randseq) md5code = get_md5(secret_key,randseq) ret = conn.recv(32).decode('utf-8') print(ret) if ret == md5code: print('是合法的客户端') chat(conn) else: print('不是合法的客户端') conn.close() sk.close() # client.py import hashlib import socket import time def get_md5(secret_key,randseq): md5 = hashlib.md5(secret_key) md5.update(randseq) res = md5.hexdigest() return res def chat(sk): while true: sk.send(b'hello') msg = sk.recv(1024).decode('utf-8') print(msg) time.sleep(0.5) sk = socket.socket() sk.connect(('127.0.0.1',9000)) secret_key = b'alexsb' randseq = sk.recv(32) md5code = get_md5(secret_key,randseq) sk.send(md5code.encode('utf-8')) chat(sk) sk.close()
# 方式二: # server.py import os import hmac import socket def get_hmac(secret_key,randseq): h = hmac.new(secret_key,randseq) res = h.digest() return res def chat(conn): while true: msg = conn.recv(1024).decode('utf-8') print(msg) conn.send(msg.upper().encode('utf-8')) sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() secret_key = b'alexsb' while true: conn,addr = sk.accept() randseq = os.urandom(32) conn.send(randseq) hmaccode = get_hmac(secret_key,randseq) ret = conn.recv(16) print(ret) if ret == hmaccode: print('是合法的客户端') chat(conn) else: print('不是合法的客户端') conn.close() sk.close() # client.py import socket import time import hmac def get_hmac(secret_key,randseq): h = hmac.new(secret_key,randseq) res = h.digest() return res def chat(sk): while true: sk.send(b'hello') msg = sk.recv(1024).decode('utf-8') print(msg) time.sleep(0.5) sk = socket.socket() sk.connect(('127.0.0.1',9000)) secret_key = b'alexsb' randseq = sk.recv(32) hmaccode = get_hmac(secret_key,randseq) sk.send(hmaccode) chat(sk) sk.close()
四、直接实现tcp协议可并发
-
socketserver模块 直接实现tcp协议可并发的server端
# server.py import socketserver class myserver(socketserver.baserequesthandler): def handle(self): # 自动触发了handle方法,并且self.request == conn msg = self.request.recv(1024).decode('utf-8') self.request.send('1'.encode('utf-8')) msg = self.request.recv(1024).decode('utf-8') self.request.send('2'.encode('utf-8')) msg = self.request.recv(1024).decode('utf-8') self.request.send('3'.encode('utf-8')) server = socketserver.threadingtcpserver(('127.0.0.1',9000),myserver) server.serve_forever() # client1.py import socket sk = socket.socket() sk.connect(('127.0.0.1',9000)) for i in range(3): sk.send(b'hello,yuan') msg = sk.recv(1024) print(msg) sk.close() # client2.py import socket sk = socket.socket() sk.connect(('127.0.0.1',9000)) for i in range(3): sk.send(b'hello,wusir') msg = sk.recv(1024) print(msg) sk.close()
推荐阅读
-
正则表达式匹配手机号格式(python正则表达式匹配汉字方法)
-
Android学习笔记--Activity中使用Intent传值示例代码
-
Android学习笔记--通过Application传递数据代码示例
-
append函数是什么意思(python入门详细教程)
-
免费云笔记哪个好用(手机上做笔记的app推荐)
-
Android学习笔记--使用剪切板在Activity中传值示例代码
-
append函数是什么意思(python入门详细教程)
-
正则表达式匹配手机号格式(python正则表达式匹配汉字方法)
-
Win10笔记本出现F5521gw未知设备的解决方法
-
python自带数据库好用吗(揭秘SQLite数据库优劣势)