网路编程之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黏包现象
随机推荐
- 20191105 《Spring5高级编程》笔记-第12章
第12章 使用Spring远程处理 12.4 在Spring中使用JMS 使用面向消息的中间件(通常成为MQ服务器)是另一种支持应用程序间通信的流行方法.消息队列(MQ)服务器的主要优点在于为应用程序 ...
- Leveldb源码分析--1
coming from http://blog.csdn.net/sparkliang/article/details/8567602 [前言:看了一点oceanbase,没有意志力继续坚持下去了,暂 ...
- [2019杭电多校第八场][hdu6667]Roundgod and Milk Tea
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6667 题目大意是说n个班级,每个班级有ai人和bi杯茶,每个人只能喝其他班的茶并且只能喝一杯.问最多有 ...
- Appium+Python之生成html测试报告
思考:测试用例执行后,如何生成一个直观漂亮的测试报告呢? 分析:1.unittest单元测试框架本身带有一个textTestRunner类,可以生成txt文本格式的测试报告,但是页面不够直观 2.我们 ...
- Scrapy框架的应用
一, Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍.所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具有 ...
- 初学css list-style属性
网上很多css布局中会看到这样的一句:list-style:none: 那么list-style到底什么意思?中文即:列表样式:无: 其实它是一个简写属性,包含了所有列表属性,具体包含list-sty ...
- 08-js流程控制、循环、元素操作
# js流程控制 > 流程控制用于基于不同的条件来执行不同的动作. ### if语句 >if... else ... >if ... else if ... else... > ...
- 02-CSS简介和基本选择器
# CSS为了让网页元素的样式更加丰富,也为了让网页的内容和样式能拆分开,CSS由此思想而诞生,CSS是 Cascading Style Sheets 的首字母缩写,意思是层叠样式表.有了CSS,ht ...
- ActiveMQ的介绍及使用
一.消息中间件概述 什么是消息中间件 发送者将消息发送给消息服务器,消息服务器将消感存放在若千队列中,在合适的时候再将消息转发给接收者. 这种模式下,发送和接收是异步的,发送者无需等待; 二者的生命周 ...
- VS Code 设置双快捷键(快速移动光标)
平时写代码会经常用到上下左右键,比如打出两个括号 () ,编辑完之后得按到右括号后面 难免有这样的场景需要在编辑代码的时候小范围地移动光标,笔者在别的ide的习惯是通过“alt + jkli”来实现光 ...