网路编程之socket与 socketserver、黏包
socket与socketerver才是我们学习python中网络编程的重中之重在介绍他们两个之前我先介绍一些相关知识
一.socket 概念
咱们现在ois模型中找到socket所承担的角色

socket处于应用层与传输层之间的软件抽象层,是一组接口,在设计模式中,socket其实就是一个门面模式,他把复杂的TCP\IP协议都隐藏在socket接口后门,对于用户来说一组简单的接口就是全部,让socket去组织数据以符合指定的协议,很相似与一个模块的功能
二.套接字(socket)
套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。
我们在网络基础里面举的例子就是TCP协议利用套接字做的简单的网络连接
三 黏包
黏包的成因
当发送端缓冲区的长度大于网卡的MTU时,TCP会将这次发送的数据拆成几个数据包发送出去,MTU是Maximum Transmission Unit的缩写意思是网络上传送的最大数据包,MTU 的单位是字节,大部分网络设备的MTU都是1500,如果本机的MTU比网关的MTU大,大的数据包就会被拆开来传送,这样会产生很多的数据包碎片,增加丢包率,降低网络速度.
基于TCP的套接字客户端往服务端上传文件,发送时文件内容是按照一段一段的字节流发送的,在接收方看了,根本不知道文件的字节流是从何开始,在何处结束
此外,发送方引起的黏包是有TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送,一个TCP段,若连续几次需要send 的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了黏包的数据,
但是要注意一点是在UDP中就不会发生黏包
因为UDP是无连接的,面向消息的,提供高效服务,说白了它发出去的东西它是不管的,收到也好收不到也好跟他没关系,所以它才效率高
在它的内部块不使用优化算法,由于UDP支持的是一对多的模式,所以接受端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的 UDP包,在每一个TDP包中就有了消息头,这样对于接受端来说就容易进行分区处理了,即面向消息的通道是有消息保护边界的.
对于空消息:TCP是基于数据流的,于是收发消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,而udp是基于数据报的,即便是你输入的是空内容,也可以被发送,udp协议会帮助你封装上消息头发送过去
不可靠不黏包的udp协议:udp的recvfrom是阻塞的,一个recvfrom必须对唯一sendinto接受完字节的数据就算完成所以数据根本不会 黏包只会丢失,不可靠
补充说明
用UDP协议发送时,用sendto函数最大能发送数据的长度为:- IP头() – UDP头()=65507字节。用sendto函数发送数据时,如果发送数据长度大于该值,则函数会返回错误。(丢弃这个包,不进行发送)
用TCP协议发送时,由于TCP是数据流协议,因此不存在包大小的限制(暂不考虑缓冲区的大小),这是指在用send函数时,数据长度参数不受限制。而实际上,所指定的这段数据并不一定会一次性发送出去,如果这段数据比较长,会被分段发送,如果比较短,可能会等待和下一次数据一起发送。
总结
黏包现象只发生在TCP协议中:
1.从表面上看,黏包问题主要是因为发送方和接受方的缓存机制,TCP协议面向流通信的特点
2.实际上主要还是因为接收方不知道消息之间的界限,不知道一次性取多少字节的数据造成的
黏包的解决方案
问题的根源在于,接受端不知道发送端将要传输的字节流长度,所以解决黏包的方法就是围绕,如何让发送端在发送数据前,将自己将要发送的字节流大小让接收端知道,然后接受端来一个死循环接收完所有的数据
服务端
import socket
server = socket.socket()
server.bind(("127.0.0.1"))
server.listen()
while True:
conn,addr = s.accept ()
while True:
msg = conn.recv()
if not data : break
res = subprocess.Popen msg.decode("utf8"),shell = True ,
stdin = subpross.PIPE,
stderr = subprocess.PIPE,
stdout = subprocess.PIPE)
err = res.stderr.read()
if err:
ret = err
else:
ret = res.studout.read()
data_lenhth =len(ret)
conn.send(str(data_length).encode("utf8"))
data = conn.recv ().decode("utf8")
if data == "recv_ready":
conn,sendall(ret)
conn.close()
客户端
import socket,time
client = socket.socket
client.connect(("127.0.0.1),8001) while True:
msg = input(">>>").strip()
if len(msg) == :continue
if msg =="quit ":break s.send (msg.encode("utf8"))
length= int(s.recv().decode("utf8"))
s.send("recv_ready".encode(utf8))
send_size =
recv_size =
data = b""
while recv_size <length:
data+=s.recv()
recv_size += len(data) print(data.decode("utf9")
虽然这样做解决了黏包的问题,但是随之而来的新问题有产生了在程序运行速度远大于网络传输速度,所以在发送一段字节前先用send发送该字节流的长度,这种方式会放大网络延迟带来的性能损耗
所以我们引出struct模块
这个模块可以把一个类型转换成固定的长度的Bytes
网路编程之socket与 socketserver、黏包的更多相关文章
- Python自动化运维之15、网络编程之socket、socketserver、select、twisted
一.TCP/IP相关知识 TCP/UDP提供进程地址,两个协议互不干扰的独自的协议 TCP :Transmission Control Protocol 传输控制协议,面向连接的协议,通信 ...
- python(十三):网络编程之socket与socketserver
socket是操作系统中I/O系统延伸部分,支持TCP和UDP等网络通信协议,它使计算机之间(或其本身)的进程通信称为可能.socket中的socket()函数.recv()函数和send()函数,相 ...
- Python之网路编程之socket简单介绍
一.网络协议 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构(互联网中处处是C/S架构):B/S架构也是C/S架构的一种,B/S是浏览器/服务器 C/S架构与socket的关系: ...
- 网络编程之socket
网络编程之socket socket:在网络编程中的一个基本组件,也称套接字. 一个套接字就是socket模块中的socket类的一个实例. 套接字包括两个: 服务器套接字和客户机套接字 套接字的实例 ...
- 网络编程之Socket & ServerSocket
网络编程之Socket & ServerSocket Socket:网络套接字,网络插座,建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API),对TCP/IP ...
- GO语言的进阶之路-网络编程之socket
GO语言的进阶之路-网络编程之socket 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是socket; 在说socket之前,我们要对两个概念要有所了解,就是IP和端口 ...
- [深入浅出Cocoa]iOS网络编程之Socket
http://blog.csdn.net/kesalin/article/details/8798039 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] [深入浅出Co ...
- 网络编程之Socket代码实例
网络编程之Socket代码实例 一.基本Socket例子 Server端: # Echo server program import socket HOST = '' # Symbolic name ...
- Python网络编程基础 ❷ 基于upd的socket服务 TCP黏包现象
TCP的长连接 基于upd的socket服务 TCP黏包现象
随机推荐
- oracle--本地网络配置tnsnames.ora和监听器listener.ora
文件tnsnames.ora 是给orcl客户端使用 配置本地网络服务:(客户端) 第一种使用暴力方式直接操作: 修改:C:\app\Administrator\product\11.2.0\dbho ...
- Node.js实战13:fs模块奥义!开发一个数据库。
本文,将使用fs开发一种简单的文件型数据库. 数据库中,记录将采用JSON模式,内容型如: {"key":"a","value":" ...
- STL 配接器(adapters)
定义 配接器(adapters):将一个class的接口,转换为另一个class的接口,使得原来不能一起使用相互兼容的classes,可以一起协同工作. 配接器是一种设计模式. STL中提供的各种配接 ...
- AngularJs——基础小知识(二)
AngularJs的过滤器 1.Currency :过滤器(金额货币格式化)
- ### Error building SqlSession. ### The error may exist in SQL Mapper Configuration ### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibat
这是一个由粗心导致的错误,具体报错如下: org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSessio ...
- Java中的容器(集合)
1.Java常用容器:List,Set,Map List: 继承了Collection接口(public interface List<E> extends Collection<E ...
- Oracle数据库SQL语句的分类
1986年10月,美国国家标准协会对SQL进行规范后,以此作为关系式数据库管理系统的标准语言,1987年在国际标准组织的支持下成为国际标准.不过各种通行的数据库系统其实在实践过程中都对SQL规范的作了 ...
- 谈Apache OFbiz 会员模块表结构设计
数据库表的结构设计可谓是ofbiz除技术框架之外,另一个非常值得学习的方向.这篇文章我们来谈谈ofbiz对电子商务会员表的设计. PARTY ofbiz对人.团体进行了抽象,称之为party,翻译为中 ...
- 三:GC回收机制
jvm垃圾回收机制: jvm中有个垃圾回收线程,它是低优先级的,当虚拟机空闲或堆内存不足时,它就会去清除不可达对象. GC是如何去判断对象是否能被回收的 早期GC判断对象是否能被回收时用的引用计数法, ...
- sqlserver 高版本迁移到低版本
奇葩事不少, 这不, 得把 sqlserver 2014 迁移到 2012 开始以为用备份再还原的方法就可以, 谁知道最终兼容性的问题无法解决(低版本不兼容高版本备份的文件, 即便在高版本中选择了兼 ...