11.1、socket连接中的粘包、精确传输问题
粘包:
发生原因:
当调用send的时候,数据并不是即时发给客户端的。而是放到了系统的socket发送缓冲区里,等缓冲区满了、或者数据等待超时了,数据才会发送,所以有时候发送太快的话,前一份数据还没有传给客户端,那么这份数据和上一份数据一起发给客户端的时候就会造成“粘包” 。
解决方案:
解决根源的思想是避免不同段的数据一起发送。
- 方案1:前一段数据send完后,等待一段时间再send第二段数据。缺点:时间效率低,而且也无法完全避免问题【因为不清楚该设置多少时间才能保证前一份数据已经发送】
- 方案2:握手机制:前一段数据send完后,尝试recv,等待客户端回应,确认第一段数据发送完后,再send第二段数据。完美方案?
方案二的演示:
服务端【发送方】代码:
import socket server=socket.socket()
server.bind(("localhost",1234))
server.listen() while True:
print("正在等待。。。")
conn,addr=server.accept()
while True:
try:
conn.send(b"first info")
ack=conn.recv(1024) #接收客户端确认
print(ack)
conn.send(b"second info")
except ConnectionResetError as e:
print(e)
break server.close()
客户端【接收方】代码:
import socket client=socket.socket() client.connect(("localhost",1234)) data=client.recv(1024)
print(data.decode())
client.send(b"ack")#发送确认
data=client.recv(1024)
print(data.decode())
client.close()
不精确传输问题:
发生原因:
由于数据太大,发送方一次send不完,而接收方只recv一次,使得影响了后面数据的传输
解决方案:
解决根源的思想是改变recv的次数。
- 方案:将数据的大小发给接收方,让接收方来决定recv的次数
方案实现代码【以解决长数据shell命令传输为例】:
服务端【发送方】:
import socket,os server=socket.socket()
server.bind(("localhost",1234))
server.listen()
while True:
print("正在等待...")
conn,addr=server.accept()
print("连接成功!")
while True:
try:
cmd=conn.recv(1024)
data=os.popen(cmd.decode()).read()
# print(data)
cmd_len=len(data.encode())
print(cmd_len)
#发现这里如果cmd_len为0会导致异常,有些是没有返回值的command
if cmd_len==0:
data="command has nothing return"
cmd_len=len(data.encode())
##因为这里前面没有发送操作,所以不用担心粘包,如果有则要考虑处理
conn.send(str(cmd_len).encode())#因为len结果是int,所以还要转换
#这里要处理粘包
ack=conn.recv(1024)
conn.send(data.encode())
except ConnectionResetError as e:
print(e)
break server.close()
客户端【接收方】:
import socket client=socket.socket()
client.connect(("localhost",1234))
while True: cmd = input(">>:")
client.send(cmd.encode())
data_len=client.recv(1024)
data_len=int(data_len.decode())
print(data_len)
recv_len=0
client.send(b'ack')
total_data=b''
while recv_len<data_len:
data=client.recv(1024)
recv_len+=len(data)
total_data+=data
print(total_data.decode())
client.close()
- 利用这个原理可以实现文件传输,只要能确定接受次数,就能保证文件传输的大小正确。
11.1、socket连接中的粘包、精确传输问题的更多相关文章
- c# Socket通讯中关于粘包,半包的处理,加分割符
using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using S ...
- python socket的应用 以及tcp中的粘包现象
1,socket套接字 一个接口模块,在tcp/udp协议之间的传输接口,将其影藏在socket之后,用户看到的是socket让其看到的. 在tcp中当做server和client的主要模块运用 #s ...
- python中TCP协议中的粘包问题
TCP协议中的粘包问题 1.粘包现象 基于TCP实现一个简易远程cmd功能 #服务端 import socket import subprocess sever = socket.socket() s ...
- python中TCP粘包问题解决方案
TCP协议中的粘包问题 1.粘包现象 基于TCP写一个远程cmd功能 #服务端 import socket import subprocess sever = socket.socket() seve ...
- Netty 中的粘包和拆包
Netty 底层是基于 TCP 协议来处理网络数据传输.我们知道 TCP 协议是面向字节流的协议,数据像流水一样在网络中传输那何来 "包" 的概念呢? TCP是四层协议不负责数据逻 ...
- 什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?
只有TCP有粘包现象,UDP永远不会粘包! 粘包:在接收数据时,一次性多接收了其它请求发送来的数据(即多包接收).如,对方第一次发送hello,第二次发送world, 在接收时,应该收两次,一次是he ...
- socket基于TCP(粘包现象和处理)
目录 6socket套接字 7基于TCP协议的socket简单的网络通信 AF_UNIX AF_INET(应用最广泛的一个) 报错类型 单一 链接+循环通信 远程命令 9.tcp 实例:远程执行命令 ...
- day8---多线程socket 编程,tcp粘包处理
复习下socket 编程的步骤: 服务端: 1 声明socket 实例 server = socket.socket() #括号里不写 默认地址簇使用AF_INET 即 IPv4 ...
- python socket网络编程之粘包问题详解
一,粘包问题详情 1,只有TCP有粘包现象,UDP永远不会粘包 你的程序实际上无权直接操作网卡的,你操作网卡都是通过操作系统给用户程序暴露出来的接口,那每次你的程序要给远程发数据时,其实是先把数据从用 ...
随机推荐
- LeetCode:105_Construct Binary Tree from Preorder and Inorder Traversal | 根据前序和中序遍历构建二叉树 | Medium
要求:通过二叉树的前序和中序遍历序列构建一颗二叉树 代码如下: struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode ...
- EJB3与JPA的关系
转载自http://www.cnblogs.com/o-andy-o/archive/2012/04/17/2453537.html JPA是基于Java持久化的解决方案,主要是为了解决ORM框架的差 ...
- String-intern方法举例分析其含义
之后重新理解这个知识点时,又写了一些小例子 String a1 = new String("str01") ; String a2 = "str01" ; Sy ...
- html2canvas的踩坑之路
html2canvas的踩坑之路 前言 早有耳闻这个html2canvas比较坑,但无奈于产品需求的压迫,必须实现html转图片的功能,自此走上了填坑之路,好在最后的效果还算令人满意,这才没有误了产品 ...
- webpack-loader是怎样炼成的
目录 啰嗦两句 loader 是干什么的 loader 的工具箱 --context loader 实战 啰嗦两句 学习这件事从学习动机上来看,可以分成两种情况:主动学习和被动学习.主动学习就是,某天 ...
- salesforce零基础学习(八十八)项目中的零碎知识点小总结(二)
通过做项目以及群里面的一些大神的聊天,总结一下关于项目中的两个知识点,以后当做参考. 一. 在custom setting中配置集成接口信息后刷sandbox的问题 我们做项目时,经常会遇见和其他平台 ...
- TCP/IP 笔记 - 域名解析和域名系统
由于IP地址的烦琐导致的记忆和使用困难,互联网支持使用主机名称来识别包括客户机和服务器在内的主机.同时为了使用一系列协议,主机名称通过称为"名称解析"的过程转换成对应IP地址. 互 ...
- python-拷贝
1.普通的赋值操作 def print_id(array): ids = [] for ar in array: ids.append(id(ar)) print (array, ids) a = [ ...
- C++虚表详解
所有结果均为32位系统,指针为4个字节 简单继承 class A { public: int a; }; class B : public A { public: int b; }; 对象B的内存布局 ...
- 面试:C++不可继承类
面试中可能遇到让设计一个无法被继承的类.最简单的实现是将该类的构造函数设置为私有的,然后通过静态成员函数调用私有构造函数实例化对象,这样的类确实不可继承,但是使用起来非常不方便,必须使用静态成员实例化 ...