热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

【网络编程】第2回socket套接字和黏包

目录1OSI各层特征1.1传输层1.1.1PORT协议1.1.2本质1.1.3TCP协议1.1.3.1定义1.1.3.2三次握手1.1.3.3四次挥手1.1.3.4判断1.1.4U

目录



  • 1 OSI各层特征

    • 1.1 传输层

      • 1.1.1 PORT协议

      • 1.1.2 本质

      • 1.1.3 TCP协议

        • 1.1.3.1 定义

        • 1.1.3.2 三次握手

        • 1.1.3.3 四次挥手

        • 1.1.3.4 判断



      • 1.1.4 UDP协议

        • 1.1.4.1 定义

        • 1.1.4.2 总结

        • 1.1.1.3 对比例





    • 3. 应用层



  • 2. scoket套接字

    • 2.1 基于文件类型的套接字家族

    • 2.2 基于网路类型的套接字家族

    • 2.3 信息交互

      • 2.3.1 服务端代码

      • 2.3.2 客户端代码

      • 2.3.3 运行展示





  • 3. 代码优化

    • 3.1 代码优化讲解

      • 3.1.1 send与recv

      • 3.1.2 消息自定义

      • 3.1.3 循环通信

      • 3.1.4 服务端能够持续提供服务

      • 3.1.5 消息不能为空

      • 3.1.6 服务端频繁重启可能会被占用的错(主要针对mac电脑)

      • 3.1.7 客户端异常退出会发送空消息(针对mac linux)



    • 3.2 代码优化展示

      • 3.2.1 服务端

      • 3.2.2 客户端

      • 3.3.3 运行结果展示





  • 4. 半连接池

  • 5. 黏包

    • 5.1 定义

    • 5.2 舔包现象

      • 5.2.1 服务端代码

      • 5.2.2 客户端代码

      • 5.2.3 结果展示

      • 5.2.4 结论



    • 5.3 struct 模块

      • 5.3.1 代码讲解

      • 5.3.2 总结 思路

      • 5.3.3 图表







1 OSI各层特征

1.1 传输层


1.1.1 PORT协议

端口协议:规定了一台计算机上的每一个正在运行的应用程序都必须有一个端口号,端口号相当于是计算机用来管理多个应用程序的标记


1.1.2 本质

规定了数据传输所遵循的规则,数据传输能够遵循的协议有很多,TCP和UDP是较为常见的两个


1.1.3 TCP协议


1.1.3.1 定义

TCP--传输控制协议,提供是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。


1.1.3.2 三次握手



  1. 建立双向通道




  2. 洪水攻击:同时让大量客户端朝服务端发送建立TCP连接的请求


1.1.3.3 四次挥手



  1. 断开双向通道,中间的两步不能合并(需要有检查的时间)





1.1.3.4 判断

基于TCP传输数据非常的安全 因为有双向通道?



  1. 前半句对,后半句错

  2. 基于TCP传输数据,数据不容易丢失,不容易丢失的原因在于二次确认机制,每次发送数据都需要返回确认消息 否则在一定的时间会反复发送


1.1.4 UDP协议


1.1.4.1 定义

UDP--用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快


1.1.4.2 总结

基于UDP协议发送数据,没有任何的通道也没有任何的限制,UDP发送数据没有TCP安全(没有二次确认机制)


1.1.1.3 对比例



  1. TCP类似于打电话:你一句我一句 有来有往

  2. UDP类似于发短信:只要发送了 不管别人看没看到 也不管回不回复


3. 应用层



  1. 主要取决于程序员自己采用什么策略和协议

    常见协议有:HTTP HTTPS FTP...


2. scoket套接字

2.1 基于文件类型的套接字家族



  1. 套接字家族的名字:AF_UNIX

  2. unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信


2.2 基于网路类型的套接字家族



  1. 套接字家族的名字:AF_INET

  2. 所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET


2.3 信息交互


2.3.1 服务端代码

import socket
# 1.创捷一个socket对象
server = socket.socket() # 括号内什么都不写,默认就是基于网络的TCP套接字
# 2.绑定一个固定的地址(ip\port)
server.bind(('127.0.0.1', 8080)) # 127.0.0.1本地回环地址(只允许自己的机器访问)
# 3.半连接池
server.listen(5)
# 4.开业 等待接客
sock, address = server.accept()
print(sock, address) # sock是双向通道,address是客户端地址
# 5.数据交互
sock.send(b'hello big baby') # 朝客户端发送数据
data = sock.recv(1024) # 接收客户端发送的数据 1024bytes
print(data)
# 断开连接
sock.close() # 断链接
server.close() # 关机

2.3.2 客户端代码

import socket
# 1.产生一个socket对象
client = socket.socket()
# 2.连接服务端(拼接服务端的ip和port)
client.connect(('127.0.0.1', 8080))
# 3.数据交互
data = client.recv(1024) # 接收服务端发送的数据
print(data)
client.send(b'hello sweet server') # 朝服务端发送数据
# 4. 关闭
client.close()

2.3.3 运行展示



  1. 先运行服务端


  2. 在运行客户端


  3. 传信息再到服务端里查看



3. 代码优化

3.1 代码优化讲解


3.1.1 send与recv



  1. 客户端与服务端不能同时执行同一个

  2. 有一个收,另外一个就是发

  3. 有一个发,另外一个就是收

  4. 不能同时收或者发


3.1.2 消息自定义

input获取用户数据即可(主要编码解码)


3.1.3 循环通信

给数据交互环节添加循环即可


3.1.4 服务端能够持续提供服务

不会因为客户端断开连接而报错,异常捕获 一旦客户端断开连接 服务端结束通信循环


3.1.5 消息不能为空

判断是否为空 如果是则重新输入(主要针对客户端)


3.1.6 服务端频繁重启可能会被占用的错(主要针对mac电脑)

from socket import SOL_SOCKET,SO_REUSEADDR

server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加


3.1.7 客户端异常退出会发送空消息(针对mac linux)

针对接收的消息加判断处理即可


3.2 代码优化展示


3.2.1 服务端

import socket
from socket import SOL_SOCKET, SO_REUSEADDR
# 1.创建一个socket对象
server = socket.socket() # 括号内什么都不写 默认就是基于网络的TCP套接字
# 2.绑定一个固定的地址(ip\port)
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 就是它,在bind前加
server.bind(('127.0.0.1', 8080)) # 127.0.0.1本地回环地址(只允许自己的机器访问)
# 3.半连接池(暂且忽略)
server.listen(5)
# 4.开业 等待接客
while True:
sock, address = server.accept()
print(sock, address) # sock是双向通道 address是客户端地址
# 5.数据交互
while True:
try:
msg = input('请输入发送给客户端的消息>>>:').strip()
if len(msg) == 0: continue
sock.send(msg.encode('utf8')) # 朝客户端发送数据
data = sock.recv(1024) # 接收客户端发送的数据 1024bytes
if len(data) == 0: #
break
print(data.decode('utf8'))
except ConnectionResetError:
sock.close()
break

3.2.2 客户端

import socket
# 1.产生一个socket对象
client = socket.socket()
# 2.连接服务端(拼接服务端的ip和port)
client.connect(('127.0.0.1', 8080))
# 3.数据交互
while True:
data = client.recv(1024) # 接收服务端发送的数据
print(data.decode('utf8'))
msg = input('请输入发送给客户端的消息>>>:').strip()
if len(msg) == 0:
msg = '手抖了一下 暂无消息'
client.send(msg.encode('utf8')) # 朝服务端发送数据

3.3.3 运行结果展示




4. 半连接池

server.listen(5)

主要是为了做缓冲 避免太多无效等待


5. 黏包

5.1 定义

同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种显现就是黏包。只有TCP有粘包现象,UDP永远不会粘包


5.2 舔包现象


5.2.1 服务端代码

import socket
# 1.创建一个socket对象
server = socket.socket() # 括号内什么都不写 默认就是基于网络的TCP套接字
# 2.绑定一个固定的地址(ip\port)
server.bind(('127.0.0.1', 8080)) # 127.0.0.1本地回环地址(只允许自己的机器访问)
server.listen(5)
sock, address = server.accept()
print(sock.recv(5))
print(sock.recv(5))
print(sock.recv(5))

5.2.2 客户端代码

import socket
# 1.产生一个socket对象
client = socket.socket()
# 2.连接服务端(拼接服务端的ip和port)
client.connect(('127.0.0.1', 8080))
client.send(b'jason')
client.send(b'kevin')
client.send(b'jerry')

5.2.3 结果展示




5.2.4 结论



  1. 只有TCP有粘包现象,UDP永远不会粘包

  2. TCP特性>>流式协议:所有的数据类似于水流,连接在一起的。ps:数据量很小,并且时间间隔很多,那么就会自动组织到一起

  3. recv:我们不知道即将要接收的数据量多大,如果知道的话不会产生也不产生黏包


5.3 struct 模块


5.3.1 代码讲解

import struct
info = '下午上课 以后可能是常态!'
print(len(info)) # 13 数据原本的长度
res = struct.pack('i', len(info)) # 将数据原本的长度打包
print(len(res)) # 4 打包之后的长度是4
ret = struct.unpack('i', res) # 将打包之后固定长度为4的数据拆包
print(ret[0]) # 13 又得到了原本数据的长度
info1 = '打起精神啊 下午也需要奋斗 也需要认真听 客服困难 你困我也困!!!'
print(len(info1)) # 34
res = struct.pack('i', len(info1)) # 将数据原本的长度打包
print(len(res)) # 4 打包之后的长度是4
ret = struct.unpack('i', res)
print(ret[0]) # 34


5.3.2 总结 思路



  1. struct模块无论数据长度是多少,都可以帮你打包成固定长度,然后基于该固定长度 还可以反向解析出真实长度

  2. 思路

1. 先将真实数据的长度制作成固定长度
2. 发送送固定长度的报头
3. 再发送真实数据

1. 先接收固定长度的报头
2. 再根据报头解压出真实长度
3. 根据真实长度接收即可


  1. struct模块针对数据量特别打的数字没有办法打包


5.3.3 图表




推荐阅读
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • 本文深入探讨了如何通过调整InnoDB的关键配置参数来优化MySQL的随机IO性能,涵盖了缓存、日志文件、预读机制等多个方面,帮助读者全面提升数据库系统的性能。 ... [详细]
  • MQTT技术周报:硬件连接与协议解析
    本周开发笔记重点介绍了在新项目中使用MQTT协议进行硬件连接的技术细节,涵盖其特性、原理及实现步骤。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 几何画板展示电场线与等势面的交互关系
    几何画板是一款功能强大的物理教学软件,具备丰富的绘图和度量工具。它不仅能够模拟物理实验过程,还能通过定量分析揭示物理现象背后的规律,尤其适用于难以在实际实验中展示的内容。本文将介绍如何使用几何画板演示电场线与等势面之间的关系。 ... [详细]
  • 本文深入探讨了Linux系统中网卡绑定(bonding)的七种工作模式。网卡绑定技术通过将多个物理网卡组合成一个逻辑网卡,实现网络冗余、带宽聚合和负载均衡,在生产环境中广泛应用。文章详细介绍了每种模式的特点、适用场景及配置方法。 ... [详细]
  • 本文详细探讨了在Android 8.0设备上使用ChinaCock的TCCBarcodeScanner进行扫码时出现的应用闪退问题,并提供了解决方案。通过调整配置文件,可以有效避免这一问题。 ... [详细]
  • ImmutableX Poised to Pioneer Web3 Gaming Revolution
    ImmutableX is set to spearhead the evolution of Web3 gaming, with its innovative technologies and strategic partnerships driving significant advancements in the industry. ... [详细]
  • MongoDB集群配置:副本集与分片详解
    本文详细介绍了如何在MongoDB中配置副本集(Replica Sets)和分片(Sharding),并提供了具体的步骤和命令,帮助读者理解并实现高可用性和水平扩展的MongoDB集群。 ... [详细]
author-avatar
米粒尖尖果儿_445
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有