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. 【转帖】Windows Server 2016与旧版本系统比较

    一.性能和可扩性 特征描述 Windows Server 2012/2012 R2 标准版和数据中心 Windows Server 2016 标准版和数据中心 物理内存(主机)支持 每个物理服务器至多 ...

  2. [转帖]oom-killer错误排查过程

    https://www.cnblogs.com/hphua/p/16395893.html 1.遇到的问题:应用在hi3536上跑一段不固定的时间,随之就会出现重启的现象:打印如下: app-run ...

  3. BMC修改密码

    公司里的服务器都托管出去了, 为了好维护, 都给自己的机器设置了BMC远程管理的端口, 安全起见自己修改了密码. 方法很简单.默认用户密码是 用户:root 密码: root 用户:admin 密码: ...

  4. JAVA多线程并发编程-避坑指南

    作者:京东零售 肖朋伟 一.前言 开发过程中,多线程的应用场景可谓十分广泛,可以充分利用服务器资源,提高程序处理速度.我们通常也会使用池化技术,去避免频繁创建和销毁线程. 本篇旨在基于编码规范.工作中 ...

  5. node使用nodemailer发送邮件

    安装模块 npm install nodemailer 代码 const nodemailer = require('nodemailer'); // 查找到有关QQ邮箱的相关信息在 /node_mo ...

  6. 【NSSCTF-Round#16】 Web和Crypto详细完整WP

    每天都要加油哦!    ------2024-01-18  11:16:55 [NSSRound#16 Basic]RCE但是没有完全RCE <?php error_reporting(0); ...

  7. gRPC基本教程

    原文在这里. 本教程为Go程序员提供了使用gRPC的基本介绍. 通过跟随本示例,你将学会如何: 在.proto文件中定义一个服务. 使用协议缓冲编译器生成服务器和客户端代码. 使用Go gRPC AP ...

  8. 机器学习算法(四): 基于支持向量机的分类预测(SVM)

    机器学习算法(四): 基于支持向量机的分类预测 本项目链接:https://www.heywhale.com/home/column/64141d6b1c8c8b518ba97dcc 1.相关流程 支 ...

  9. Spring一套全通5—SSM整合

    百知教育 - Spring系列课程 - MVC框架整合 第一章.MVC框架整合思想 1. 搭建Web运行环境 <dependency> <groupId>javax.servl ...

  10. 月薪40K+的测试老兵,测试开发学习实战心得分享

    1. 前言 大家好,我是Arthur,拥有超过10年以上的银行测试经验,目前在一家互联网创业公司担任测试经理.在我们那个年代,基本上都是不会写代码的做测试工作,而且基本都是纯手工:最近几年,测试开发开 ...