网路编程之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黏包现象
随机推荐
- (136)leetcode刷题Python笔记——只出现一次的数字
题目如下: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: ...
- java中过滤器Filter的使用总结【转载】
1.看了别人写的,觉得获益匪浅,转载下为以后的使用 java中Filter的使用
- jquery点击来回切换
做个笔记偶尔用有时记不住 方法一: <div id="test"> test </div> $('#test').mouseover(function () ...
- Python:库文件
可以引用的Python文件:自己写的.py + 外部库(external libraries)
- git的基本使用方法
git的基本使用方法:https://blog.csdn.net/qq_33316091/article/details/82414389
- VBA中如何用environ$ 或 environ方法取得环境变量?
用索引号取得环境变量Sub EnumSEVars() Dim strVar As String Dim i As Long strVar = Environ$(i) & Then Exit F ...
- ORACLE之字符集修改(10g)
当从oracle服务器将数据导出成dmp文件后,再导入到本地的oracle数据库时,出现: IMP-00019: 由于 ORACLE 错误 12899 而拒绝行 IMP-00003: 遇到 ORACL ...
- JavaScript中准确的判断数据类型
在 ECMAScript 规范中,共定义了 7 种数据类型,分为基本类型和引用类型两大类. 其中: 基本类型:String.Number.Boolean.Symbol.Undefined.Null ...
- 06.Linux-RedHat系统本地yum源配置
RedHat系统 1.挂载镜像光盘[root@localhost ~]# mount /dev/sr0 /media/cdrom/ 2.创建本地yum源仓库[root@localhost ~]# cd ...
- Linux架构之Nginx 配置文件
第42章 nginx相关配置文件 1.Nginx主配置文件 路径 类型 作用 /etc/nginx/nginx.conf 配置文件 nginx主配置文件 /etc/nginx/conf.d/def ...