1.四次挥手(补充)

    客户端向服务端发送一个请求消息,断开连接(代表客户端没有数据传输了)
服务端接收请求,发出响应
等到服务端所有数据收发完毕之后
服务端向客户端发送断开连接的请求
客户端接收请求后,发出响应
等到2msl,最大报文生存时间之后
客户端与服务端彻底断开连接

2.socket

socket的意义:通络通信过程中,信息拼接的工具(中文:套接字)
# 开发中,一个端口只对一个程序生效,在测试时,允许端口重复捆绑 (开发时删掉)
# 在bind方法之前加上这句话,可以让一个端口重复使用
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

3.tcp基本语法

####客户端
import socket #1.创建一个socket对象
sk = socket.socket() #2.创建连接
sk.connect(('127.0.0.1',9000)) #3.发送数据(二进制字节流)
sk.send("今天天气真好".encode('utf-8')) #4.关闭连接
sk.close()
####服务端
'''
客户端和服务端在收发数据时
一发一收是一对,否则会导致数据异常
send 发送 recv接收
'''
import socket #1.创建socket对象
sk = socket.socket() #2.绑定对应的ip和端口(注册网络,让其他主机能够找到)
'''127.0.0.1 代表本地ip'''
sk.bind(('127.0.0.1',9000)) #3.开启监听
sk.listen() #4.创建三次握手
conn,addr = sk.accept()
print(conn,addr)
"""
conn = <socket.socket fd=456, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61176)>
addr = ('127.0.0.1', 61176)
""" #5.收发数据(recv里面的参数单位是字节,代表一次最多接受多少数据)
res = conn.recv(1024)
print(res.decode('utf-8')) #6.四次挥手
conn.close() #7.退还端口
sk.close()

4.tcp循环发消息

####客户端
# ### tcp客户端
import socket #1.创建socket对象
sk = socket.socket() #2.创建连接
sk.connect(('127.0.0.1',9000)) #3.发送数据
'''
res = sk.recv(1024) #一次接收最大字节1024
print(res)
'''
while True:
strvar = input('请输入内容')
sk.send(strvar.encode('utf-8')) res = sk.recv(1024)
if res == b'q':
break
print(res.decode('utf-8')) #4.关闭连接
sk.close()
####服务端
# ### 服务端
import socket #1.创建socket对象
sk = socket.socket() #2.注册主机绑定ip及端口
sk.bind(('127.0.0.1',9000)) #3.监听
sk.listen() #4.三次握手
# conn,addr = sk.accept() #5.接发收数据
'''
数据类型:二进制的字节流
b修饰的字符串 => 代表的是二进制的字节流
里面的字符必须是ascii编码中的字符,不能是中文,否则报错
'''
while True:
conn,addr = sk.accept()
while True:
res = conn.recv(1024)
print(res.decode('utf-8')) strvar = input('请输入内容')
conn.send(strvar.encode('utf-8'))
#退出
if strvar == 'q':
break #6.四次挥手
conn.close() #7.退还端口
sk.close()

5.udp基本语法

#### 客户端

import socket
#type = socket.SOCK_DGRAM => 返回udp协议对象 #1.创建udp对象
sk = socket.socket(type=socket.SOCK_DGRAM) #2.发送数据
msg = '大妹纸,你好啊'
#sendto (二进制字节流,(ip,端口))
sk.sendto(msg.encode('utf-8'),('127.0.0.1',9000)) #客户端接收服务端发过来的数据
msg,ser_addr = sk.recvfrom(1024)
print(msg.decode())
print(ser_addr) #3.关闭连接
sk.close()
####服务端

import socket
#type = socket.SOCK_DGRAM => 返回udp协议对象 #1.创建对象
sk = socket.socket(type=socket.SOCK_DGRAM) #2.绑定地址端口号
sk.bind(('127.0.0.1',9000)) #3.接收消息(udp作为服务端的时候,第一次一定是 接收消息)
msg,cli_addr = sk.recvfrom(1024)
print(msg.decode())
print(cli_addr) # ('127.0.0.1', 56184) #服务端给客户端发消息
msg = '我是老爷们,我不好'
sk.sendto(msg.encode(),cli_addr) #.关闭连接
sk.close()

6.黏包

# tcp协议在发送数据时,会出现黏包现象.
(1)数据粘包是因为在客户端/服务器端都会有一个数据缓冲区,
缓冲区用来临时保存数据,为了保证能够完整的接收到数据,因此缓冲区都会设置的比较大。
(2)在收发数据频繁时,由于tcp传输消息的无边界,不清楚应该截取多少长度
导致客户端/服务器端,都有可能把多条数据当成是一条数据进行截取,造成黏包

7.黏包出现的两种情况

#黏包现象一:
在发送端,由于两个数据短,发送的时间隔较短,所以在发送端形成黏包
#黏包现象二:
在接收端,由于两个数据几乎同时被发送到对方的缓存中,所有在接收端形成了黏包
#总结:
发送端,包之间时间间隔短 或者 接收端,接受不及时, 就会黏包
核心是因为tcp对数据无边界截取,不会按照发送的顺序判断

8.黏包对比:tcp和udp

#tcp协议:
缺点:接收时数据之间无边界,有可能粘合几条数据成一条数据,造成黏包
优点:不限制数据包的大小,稳定传输不丢包 #udp协议:
优点:接收时候数据之间有边界,传输速度快,不黏包
缺点:限制数据包的大小(受带宽路由器等因素影响),传输不稳定,可能丢包 #tcp和udp对于数据包来说都可以进行拆包和解包,理论上来讲,无论多大都能分次发送
但是tcp一旦发送失败,对方无响应(对方无回执),tcp可以选择再发,直到对应响应完毕为止
而udp一旦发送失败,是不会询问对方是否有响应的,如果数据量过大,易丢包

9.解决黏包的几种办法

# ### 客户端
# ### 针对于tcp协议,会出现黏包现象 import socket
import time #1.创建对象
sk = socket.socket()
#2.创建连接
sk.connect(('127.0.0.1',9000))
time.sleep(0.1) #处理收发数据逻辑
'''
res1 = sk.recv(1024)
res2 = sk.recv(1024)
print(res1)
print(res2)
'''
#先接收数据的总大小
res = sk.recv(1)
num = int(res.decode('utf-8'))
#接收num这么多的字节数
res1 = sk.recv(num) #第一次
res2 = sk.recv(1024) #第二次
print(res1)
print(res2) #4.关闭连接
sk.close()
####服务端

import socket

#1.创建对象
sk = socket.socket()
# 把这句话写在bind之前,让一个端口绑定多个程序,可以重复使用(仅用在测试环节)
#sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #2.注册主机绑定ip和端口
sk.bind(('127.0.0.1',9000)) #3.监听
sk.listen() #4.三次握手
conn,addr = sk.accept() #在发送真实数据之前,提前告诉接收端数据的大小
conn.send('5'.encode()) #处理收发数据逻辑
conn.send('hello'.encode()) #第一次发送
#time.sleep(0.1)
conn.send(',world'.encode()) #第二次发送 #6.四次挥手
conn.close() #7.退还端口
sk.close()
####客户端
# ### 针对于tcp协议,会出现黏包现象 import socket
import time #1.创建对象
sk = socket.socket()
#2.创建连接
sk.connect(('127.0.0.1',9000))
time.sleep(0.1) # 处理收发数据逻辑
'''
黏包的现象
res1 = sk.recv(1024)
res2 = sk.recv(1024)
print(res1)
print(res2)
'''
#先接收数据的总大小
res = sk.recv(8)
num = int(res.decode('utf-8'))
#接收num这么多的字节数
res1 = sk.recv(num)
res2 = sk.recv(1024)
print(res1)
print(res2) #关闭连接
sk.close()
# ### 服务端
import socket #1.创建对象
sk = socket.socket() #2.注册主机绑定ip和端口
sk.bind(('127.0.0.1',9000)) #3.监听
sk.listen #4.三次握手
conn,addr = sk.accept() #5.接发收数据处理逻辑
conn.send('00000100'.encode()) #8字节 #处理收发数据逻辑
msg = 'hello' * 20
conn.send(msg.encode())
#time.sleep(0.1)
conn.send(',world'.encode()) #6.四次挥手
conn.close() #7.退还端口
sk.close()
# ### 客户端   用struct解决
# ### 针对于tcp协议,会出现黏包现象 import socket
import time
import struct #1.创建对象
sk = socket.socket() #2.创建连接
sk.connect(('127.0.0.1',9000)) #处理收发数据逻辑
#接受第一次发送过来的数据(数据的大小)
n = sk.recv(4) #都会压缩成4个字节来接收
tup = struct.unpack("i",n) #unpack解包,'i'表示整型int,返回元组
print(tup) #(24,)
n = tup[0]
print(n) #第二次接收的真实的数据
res1 = sk.recv(n)
print(res1.decode()) #第三次接收的真实的数据
res2 = sk.recv(1024)
print(res2.decode()) #关闭连接
sk.close()
# ### 服务端
import socket
import struct #1.创建对象
sk = socket.socket() #2.注册主机绑定ip和端口
sk.bind(('127.0.0.1',9000)) #3.监听
sk.listen() #4三次握手
conn,addr = sk.accept() #5.处理收发数据逻辑
strvar = input('请输入')
msg = strvar.encode()
length = len(msg) #第一次把长度先发送过去
res = struct.pack('i',length)
conn.send(res) #第二次在发送真实数据
conn.send(msg) #第三次在发送一个数据
conn.send(',world'.encode()) #6.四次挥手
conn.close() #7.退还端口
sk.close()

10.struct用法(解决黏包)

import struct
'''
pack:
把任意长度的数字转化成具有4个字节的固定长度的字节流 unpack:
把4个字节值恢复成原本的数字,返回是元组
''' #i => int 要转化的当前数据是整型
'''pack的数值范围不是无限的,上限大概在21个亿左右,不要超过这个值'''
res = struct.pack('i',999999999)
res = struct.pack("i",1234343433)
res = struct.pack("i",2100000011)
print(res)
print(len(res)) #i => 把对应的数据转换成int,最后返回元组
tup = struct.unpack('i',res)
print(tup[0]) ## (2100000011,) '''
解决黏包场景:
应用场景在实时通讯时,需要阅读此次发的消息是什么
不需要黏包解决场景
下载或者上传文件的时候,最后要把包都结合在一起,黏包无所谓
'''

socket及黏包现象及解决黏包---day28的更多相关文章

  1. idea升级maven工程jar包版本和解决jar包冲突

    原来用过eclipse的都知道,想要升级maven工程的jar包版本或者解决jar包冲突,直接在pom文件下的dependency hierarchy视图下右击冲突的jar包,将其exclude掉,然 ...

  2. socket粘包现象加解决办法

    socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...

  3. python之路--subprocess,粘包现象与解决办法,缓冲区

    一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 std ...

  4. python--subprocess,粘包现象与解决办法,缓冲区

    一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 std ...

  5. TCP协议的粘包现象和解决方法

    # 粘包现象 # serverimport socket sk = socket.socket()sk.bind(('127.0.0.1', 8005))sk.listen() conn, addr ...

  6. 网络编程之模拟ssh远程执行命令、粘包问题 、解决粘包问题

    目录 模拟ssh远程执行命令 服务端 客户端 粘包问题 什么是粘包 TCP发送数据的四种情况 粘包的两种情况 解决粘包问题 struct模块 解决粘包问题 服务端 客户端 模拟ssh远程执行命令 服务 ...

  7. weblogic11g(10.3.6)部署war包时,解决jar包冲突的超简方案

    亲测有效:weblogic11g(10.3.6) + jdk7,打包使用jdk7或jdk8,注意weblogic用的jdk和打包时jdk的兼容. 分别配置web项目下pom.xml和weblogic. ...

  8. Python 之网络编程之socket(2)黏包现象和socketserver并发

    一:黏包 ###tcp协议在发送数据时,会出现黏包现象.     (1)数据粘包是因为在客户端/服务器端都会有一个数据缓冲区,     缓冲区用来临时保存数据,为了保证能够完整的接收到数据,因此缓冲区 ...

  9. 黏包现象、struct模块和解决黏包问题的流程、UDP协议、并发编程理论、多道程序设计技术及进程理论 _

    目录 黏包现象 二.struct模块及解决黏包问题的流程 三.粘包代码实战 UDP协议(了解) 并发编程理论 多道技术 进程理论 进程的并行与并发 进程的三状态 黏包现象 什么是粘包 1.服务端连续执 ...

  10. socket模块实现网络编程及struct模块解决黏包问题

    目录 一.socket模块 1.简介 2.基于文件类型的套接字家族 3.基于网络类型的套接字家族 二.socket代码简介 三.socket代码优化 1.聊天内容自定义 2.让聊天循环起来 3.用户输 ...

随机推荐

  1. [转帖]jmeter 使用beanshell 编写脚本

    目录 一.介绍 1.1 介绍 1.2 下载&启动 二.jmeter中创建beanshell脚本 三.jmeter与beanshell 数据交互 3.1 例子1 beanshell 将变量传给j ...

  2. [转帖]SQL Server超过了每行的最大字节数(8060)的原因和解决办法

    一.现象     出现这种错误都发生在SQL语句建表时,错误提示: "警告: 已创建表 'XXXX,但其最大行大小(10438)超过了每行的最大字节数(8060).如果结果行长度超过 806 ...

  3. Python学习之八_调用Outlook发送邮件以及调用远程windows上面的python

    Python学习之八_调用Outlook发送邮件以及调用远程windows上面的python 摘要 之前只有一个需求是发送加密邮件. 之前一直是使用linux进行发送.但是总是无法发送加密邮件. 最近 ...

  4. Windows 磁盘部分性能数据获取

    Windows 磁盘部分性能数据获取 摘要 每次晚上加班总有收获 这次发现了一个fio for windows版本的压测程序, 准备学习和使用一下. https://github.com/axboe/ ...

  5. 验证功能访问Redis的次数和命令

    背景 公司内部在进行性能调优, 调优有多个方法. 应用Redis方面主要的调优有: 1. 进行redis键值对大小的处理. 2. 进行redis键值对过期时间的处理. 3. 减少连接数,减少网络带宽. ...

  6. vue3封装搜索表单组件

    seacrch 表单完成的功能 1.根据配置json配置项自动生成表单 ok 2.是响应式的排版 ok 3.点击搜索按钮会向上抛出值 ok 4.点击重置按钮会自动清空数据,不需要父组件额外的处理 ok ...

  7. Unity的asm笔记

    使用asm的好处 减少修改C#后unity编译dll的时间,对于项目中的C#代码越多效果越明显,比如我们的一个3dmmo项目是纯C#开发,每次修改C#后编译时间就要26s以上 在Unity2018.2 ...

  8. MySQL拓展知识

    一:视图 1:创建视图 1 --格式:CREATE VIEW 视图名称 AS SQL语句 2 CREATE VIEW v1 AS 3 SELET nid, 4 name 5 FROM 6 A 7 WH ...

  9. 网友感到担忧!iOS 17支持第三方应用商店:这下跟安卓没区别了

    苹果此前官宣将于6月6日召开WWDC2023大会,按照往年的惯例,在这次大会上将会推出下一代iOS系统,也就是iOS 17.最近国外有关iOS 17的爆料中提到,迫于欧盟法案压力,iOS 17或将支持 ...

  10. 【技能篇】解决vs编译器scanf等函数不安全问题【手把手操作-一分钟解决】

    [技能篇]解决Vs编译器scanf等函数不安全问题 文章目录 说在前面 博主给大家的福利 解决方案 解决过程 尾声 说在前面 大家刚开始学习编程的时候,使用vs编译器.使用scanf等函数的时候遇到的 ...