2019-04-10-day029-粘包处理
内容回顾
osi五层协议
- 不是真实存在的,只是抽象出来的模型
- 应用层
- 传输层 TCP/UDP
- TCP :全双工,可靠的,面向连接的,速度慢,对数据大小没有限制
- 建立连接 :三次握手 SYN ACK
- 断开连接 :四次挥手 FIN ACK
- UDP :不可靠,无连接的,速度快,对数据大小有限制
- TCP :全双工,可靠的,面向连接的,速度慢,对数据大小没有限制
- 网络层 arp(ip-->mac) rarp(mac-->ip)
- 数据链路层 arp(ip-->mac) rarp(mac-->ip)
- 物理层 网线
TCP/IP 也是抽象出来的模型
struct 模块
import struct
ret = struct.pack('i',112849)
print(ret)
ret2 = struct.unpack('i',ret)
print(ret2)
总结
- 黏包现象 发送的两条数据粘在一起了
- 成因 :
- 发送端粘 : 合包机制
- 接收端粘 : 接收不及时
- 数据与数据之间是无边界的流式传输
- 解决黏包现象
- 自定义协议
- struct模块
- 把任意长度的数字变成固定的4个字节
- 低级
- 先发送数据的长度
- 再发送数据
- 高级
- 先把所有想发送的数据信息放在字典里
- 发送字典的长度
- 发送字典
- 发送涉及的数据
##作业:
- struct模块
- 自定义协议
- 默写 黏包协议
- 上传大文件(文件\视频\图片)
- 和你的同桌调通 从你的计算机上传一个视频到你同桌的电脑上
- 进阶 : 带上登录
课上代码
登陆一
server:
import sys
import json
import socket
import hashlib
def get_md5(username,password):
md5 = hashlib.md5(username.encode('utf-8'))
md5.update(password.encode('utf-8'))
return md5.hexdigest()
def login(dic_msg):
print(dic_msg['user'], dic_msg['pwd'])
with open('userinfo', encoding='utf-8') as f:
for line in f:
user, pwd = line.strip().split('|')
if user == dic_msg['user'] and pwd == get_md5(dic_msg['user'], dic_msg['pwd']):
return {'opt':'login','result':True}
else:return {'opt':'login','result':False}
sk= socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
while True:
conn,addr = sk.accept()
msg = conn.recv(1024).decode('utf-8')
dic_msg = json.loads(msg)
if hasattr(sys.modules[__name__],dic_msg['operate']):
ret = getattr(sys.modules[__name__],dic_msg['operate'])(dic_msg)
content = json.dumps(ret).encode('utf-8')
conn.send(content)
conn.close()
sk.close()
Client
import json
import socket
username = input('用户名 :')
password = input('密 码 :')
sk = socket.socket()
sk.connect(('127.0.0.1',9001))
msg = {'operate':'login',
'user':username,
'pwd':password}
str_msg = json.dumps(msg)
sk.send(str_msg.encode('utf-8'))
content = sk.recv(1024)
str_content = content.decode('utf-8')
dic_content = json.loads(str_content)
if dic_content['result']:
print('登录成功')
else:
print('登录失败')
sk.close()
登陆二
Server
import sys
import json
import socket
import hashlib
def get_md5(username,password):
md5 = hashlib.md5(username.encode('utf-8'))
md5.update(password.encode('utf-8'))
return md5.hexdigest()
def login(dic_msg):
print(dic_msg['user'], dic_msg['pwd'])
with open('userinfo', encoding='utf-8') as f:
for line in f:
user, pwd = line.strip().split('|')
print(pwd,get_md5(dic_msg['user'], dic_msg['pwd']))
if user == dic_msg['user'] and pwd == get_md5(dic_msg['user'], dic_msg['pwd']):
return {'opt':'login','result':True}
else:return {'opt':'login','result':False}
sk= socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
while True:
conn,addr = sk.accept()
msg = conn.recv(1024).decode('utf-8')
dic_msg = json.loads(msg)
if hasattr(sys.modules[__name__],dic_msg['operate']):
ret = getattr(sys.modules[__name__],dic_msg['operate'])(dic_msg)
content = json.dumps(ret).encode('utf-8')
conn.send(content)
conn.close()
sk.close()
Client
import json
import socket
import hashlib
def get_md5(username,password):
md5 = hashlib.md5(username[::2].encode('utf-8'))
md5.update(password.encode('utf-8'))
return md5.hexdigest()
username = input('用户名 :')
password = input('密 码 :')
sk = socket.socket()
sk.connect(('127.0.0.1',9001))
msg = {'operate':'login',
'user':username,
'pwd':get_md5(username,password)}
str_msg = json.dumps(msg)
sk.send(str_msg.encode('utf-8'))
content = sk.recv(1024)
str_content = content.decode('utf-8')
dic_content = json.loads(str_content)
if dic_content['result']:
print('登录成功')
else:
print('登录失败')
sk.close()
黏包练习
Server
import struct
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
conn,addr = sk.accept()
num = conn.recv(4)
num = struct.unpack('i',num)[0]
file_name = conn.recv(num).decode('utf-8')
filesize = conn.recv(4)
filesize = struct.unpack('i',filesize)[0]
with open(file_name,'wb') as f:
content = conn.recv(filesize)
f.write(content)
conn.close()
sk.close()
Client
import os
import struct
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9001))
filepath = input('请输入文件路径 :')
filename = os.path.basename(filepath).encode('utf-8')
name_len = struct.pack('i',len(filename))
sk.send(name_len)
sk.send(filename)
filesize = os.path.getsize(filepath)
file_len = struct.pack('i',filesize)
sk.send(file_len)
with open(filepath,'rb') as f:
content = f.read()
sk.send(content)
sk.close()
# 先发送字典的长度
# 再发字典 {'filename':xxxx,'filesize':xxxxx}
# 再发文件内容
黏包现象
Server
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
conn,addr = sk.accept()
conn.send(b'0015hello,你好么')
conn.send(b'5world')
conn.close()
sk.close()
Client
import time
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9001))
time.sleep(0.1)
num= sk.recv(2).decode('utf-8')
num = int(num)
msg1 = sk.recv(num)
num= sk.recv(1).decode('utf-8')
num = int(num)
msg2 = sk.recv(num)
print(msg1,msg2)
sk.close()
黏包现象2
Server
import struct
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
conn,addr = sk.accept()
str_msg = 'hello,你好么'
byets_msg = str_msg.encode('utf-8')
num = len(byets_msg)
len_bytes = struct.pack('i',num)
conn.send(len_bytes)
conn.send(byets_msg)
conn.send(b'world')
conn.close()
sk.close()
Client
import time
import struct
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9001))
time.sleep(0.1)
num= sk.recv(4)
num = struct.unpack('i',num)[0]
msg2 = sk.recv(num)
print(msg2.decode('utf-8'))
print(sk.recv(1024))
sk.close()
黏包协议
Server
import json
import struct
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
conn,addr = sk.accept()
num = conn.recv(4)
num = struct.unpack('i',num)[0]
str_dic = conn.recv(num).decode('utf-8')
dic = json.loads(str_dic)
with open(dic['filename'],'wb') as f:
content = conn.recv(dic['filesize'])
f.write(content)
conn.close()
sk.close()
Client
import os
import json
import struct
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9001))
filepath = input('请输入文件路径 :')
filename = os.path.basename(filepath)
filesize = os.path.getsize(filepath)
dic = {'filename':filename,'filesize':filesize}
str_dic = json.dumps(dic)
bytes_dic = str_dic.encode('utf-8')
len_dic = len(bytes_dic)
bytes_len = struct.pack('i',len_dic)
sk.send(bytes_len)
sk.send(bytes_dic)
with open(filepath,'rb') as f:
content = f.read()
sk.send(content)
sk.close()
# 先发送字典的长度
# 再发字典 {'filename':xxxx,'filesize':xxxxx}
# 再发文件内容
一对多人聊天
Server
import json
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',9001))
user_info = {
1234:('alex','\033[1;32m'),
5678:('宝元','\033[1;31m'),
}
while True:
msg,addr = sk.recvfrom(1024)
str_msg = msg.decode('utf-8')
dic_msg = json.loads(str_msg)
code = dic_msg['code']
content = dic_msg['msg']
print('%s%s : %s\033[0m'%(user_info[code][1],user_info[code][0],content))
ret = input('>>>').encode('utf-8')
sk.sendto(ret,addr)
sk.close()
ClientI
import json
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
addr = ('127.0.0.1',9001)
code = 5678
while True:
msg = input('>>>')
if msg.upper() == 'Q': break
send_msg = {'code':code,'msg':msg}
str_msg = json.dumps(send_msg)
sk.sendto(str_msg.encode('utf-8'),addr)
ret = sk.recv(1024).decode('utf-8')
if ret.upper() == 'Q': break
print(ret)
sk.close()
ClientII
import json
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
addr = ('127.0.0.1',9001)
code = 1234
while True:
msg = input('>>>')
if msg.upper() == 'Q':break
send_msg = {'code':code,'msg':msg}
str_msg = json.dumps(send_msg)
sk.sendto(str_msg.encode('utf-8'),addr)
ret = sk.recv(1024).decode('utf-8')
if ret.upper() == 'Q':break
print(ret)
sk.close()
2019-04-10-day029-粘包处理的更多相关文章
- 2019.04.10打卡(HTML)
代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...
- Python网络编程04 /recv工作原理、展示收发问题、粘包现象
Python网络编程04 /recv工作原理.展示收发问题.粘包现象 目录 Python网络编程04 /recv工作原理.展示收发问题.粘包现象 1. recv工作原理 2. 展示收发问题示例 发多次 ...
- TCP粘包拆包问题
阿π 专注于网络协议,系统底层,服务器软件 C++博客 | 首页 | 发新随笔 | 发新文章 | | | 管理 Socket粘包问题 这两天看csdn有一些关于socket粘包,socket缓冲区设置 ...
- 基于tcp协议下粘包现象和解决方案,socketserver
一.缓冲区 每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区.write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送 ...
- Socket/TCP粘包、多包和少包, 断包
转发: https://blog.csdn.net/pi9nc/article/details/17165171 为什么TCP 会粘包 前几天,调试mina的TCP通信, 第一个协议包解析正常,第二个 ...
- Socket粘包问题
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...
- netty 解决TCP粘包与拆包问题(一)
1.什么是TCP粘包与拆包 首先TCP是一个"流"协议,犹如河中水一样连成一片,没有严格的分界线.当我们在发送数据的时候就会出现多发送与少发送问题,也就是TCP粘包与拆包.得不到我 ...
- TCP拆包粘包之分隔符解码器
TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...
- day8---多线程socket 编程,tcp粘包处理
复习下socket 编程的步骤: 服务端: 1 声明socket 实例 server = socket.socket() #括号里不写 默认地址簇使用AF_INET 即 IPv4 ...
- socket 粘包问题(转)
https://www.v2ex.com/t/234785#reply3 1. 面向字节流的 IO 都有这个问题. socket 中 tcp 协议是面向流的协议,发送方发送和接收方的接收并不是一一对应 ...
随机推荐
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
- shift键有什么用?怎么用?shift键的妙用
一.当你用QQ和别人聊天时,是不是有时信息发送的特别慢呀,不要紧,只要你发信息时按shift 键信息就会很快的发送出去的! 二.当你面对一大堆窗口,却要一个一个把它们关掉时.是不是很烦啊.只要你按sh ...
- C语言实例:函数指针
函数指针:函数指针数组的使用: 不带参数和返回值的函数指针: #include <stdio.h> #include <stdlib.h> //定义一个没有返回值也没有入口参数 ...
- sed 正则的一个小问题
有一段类似以下的文本 aabbccc test[3307]112323553-66778tp aooppx69tp ooppsg aabbccc test[3307]1127233-6674tp bo ...
- iOS开发 -------- Block技术中的weak - strong
一 Block是什么? 我们使用^运算符来声明一个Block变量,而且在声明完一个Block变量后要像声明普通变量一样,后面要加; 声明Block变量 int (^block)(int) = NULL ...
- Base64 空格,加号问题
缘由: 在一个项目中,app请求tcpdump日志与记录的日志内容不一致 请求%2B 识别成 + 请求 + 识别成 空格 这个在base64解密的时候会出现异常,base64需要的是加号,而不是空格 ...
- 【做题】agc006e - Rotate 3x3——分析&思维
原文链接 https://www.cnblogs.com/cly-none/p/9800105.html 题意:给出一个三行\(n\)列的矩阵.问它能否由满足\(a_{ij} = 3(j-1) + i ...
- (转载)Unity 关于动态监听时,点击Button,返回其在数组中的下标
其实是绕了一圈,把数组里的元素放进数组列表里再读取它的下标 using System.Collections; using System.Collections.Generic; using Unit ...
- JS模态框 简单案例
演示: <!doctype html> <html lang="en"> <head> <meta charset="UTF-8 ...
- Appium Desktop-Permission to start activity denied.
可能情况1:activity查找错误 如何查找activity (1)确保手机和电脑已连接 adb devices (2)确保在你手机上,要测试的包启动着 (3)dos运行:adb shell d ...