首页 > 其他分享 >25. Socket与粘包问题

25. Socket与粘包问题

时间:2024-08-27 22:14:42浏览次数:4  
标签:info 25 socket server 粘包 client 接字 客户端 Socket

1. Socket概念

Socket允许应用程序通过它发送或接收数据,对其进行像对文件一样的打开、读写和关闭等操作,从而允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。Socket是应用层与传输层之间的接口,提供了一种标准的通信方式,使得不同的程序能够在网络上进行数据交换。

 

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面
对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
也有人将socket说成ip+port
ip是用来标识互联网中的一台主机的位置
而port是用来标识这台机器上的一个应用程序
ip地址是配置到网卡上的
而port是应用程序开启的
ip与port的绑定就标识了互联网中独一无二的一个应用程序
而程序的pid是同一台机器上不同进程或者线程的标识

本机中的不同程序之间交互 借助 SOCKET

2. 套接字

2.1 套接字起源

套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。
因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字” 一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯,这也被称进程间通讯或 IPC。

套接字有两种:基于文件型的、基于网络型的

2.2 基于文件型的套接字

名称:AF_UNIX

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

2.3 基于网络型的套接字

名称: AF_INET

(还有AF_INET6被用于ipv6,还有一些其他的地址族,AF_INET是使用最广泛的一个) python支持很多种地址族,网络编程大部分只使用AF_INET

2.4 套接字工作流程

以打电话模型来说明

(1)服务端---接电话

1.拥有一台手机

2.插上手机卡

3.开机等待别人打电话进来

4.接听来电

5.听到对方说话信息

6.给对方回话

7.挂断电话

8.关机

(2)客户端---打电话

1.拥有一台手机

2.插上手机卡

3.获取对方手机号,拨打电话

4.向对方说话

5.听到对方回话

6.挂断电话

7.关机

2.5 TCP套接字模型一

打电话模型

# (1)服务端---接电话
import socket

# 1.拥有一台手机    family:使用的是基于网络的套接字族  type:流式套接字  proto是一个默认参数为-1,当默认-1时该值为0
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0)
# 2.插上手机卡
addr = '127.0.0.1'
port = 9000
server.bind((addr, port))  # 绑定(主机,端口号)到套接字
# 3.开机等别人打电话进来,括号内为空默认5个
server.listen(5)
# 4.别人打电话进来,接听电话
client_socket, client_addr = server.accept()
print(client_socket)
# <socket.socket fd=404, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 8307)>
print(client_addr)
# ('127.0.0.1', 8307)
# 5.接收对方的信息
info_from_client = client_socket.recv(1024)  # 一次接收多少字节的数据
print(f'对方信息内容为:{info_from_client.decode("utf-8")}')  # 传输的数据格式为二进制,解码后再展示
# 对方信息内容为:你好,这里是客户端
# 6.给对方回信息
info_to_client = f'你好,这里是服务端'
client_socket.send(info_to_client.encode("utf-8"))  # 编码后再传输
# 7.挂断电话
client_socket.close()
# 8.关机
server.close()
# (2)客户端---打电话
import socket

# 1.拥有一台手机
client = socket.socket()  # 括号里面不填,默认为基于网络套接字模型、tcp协议
# 2.插上手机卡
addr = '127.0.0.1'
port = 9001
# 3.获取对方手机号并拨打
client.connect(('127.0.0.1', 9000))
# 4.向对方说话
info_to_server = f'你好,这里是客户端'
client.send(info_to_server.encode())  # 编码后才能传输
# 5.听到对方回话
info_from_server = client.recv(1024)  # 一次接收1024字节的数据
print(f'对方回复内容为:{info_from_server.decode()}')  # 解码
# 对方回复内容为:你好,这里是服务端
# 6.挂断电话  7.关机
client.close()

模板

# (1)服务端
import socket

server = socket.socket()  # 创建服务端对象
server.bind(('127.0.0.1', 9000))  # 绑定ip与端口
server.listen(5)  # 监听客户端的连接
conn, addr = server.accept()  # 接收到客户端的连接
recv_info = conn.recv(1024)  # 接收客户端的二进制数据
send_info = ''  # 向客户端发送数据
conn.send(send_info.encode('utf-8'))
conn.close()  # 断开客户端连接
server.close()  # 关闭服务端
# (2)客户端
import socket

client = socket.socket()  # 创建客户端对象
client.connect(('127.0.0.1', 9000))  # 连接服务端ip和端口,在这个例子中不写客户端ip和端口也行,只要有对方的就能进行通信
send_info = ''  # 发送数据
client.send(send_info.encode())
recv_info = client.recv(1024)  # 接收服务端返回的信息
client.close()  # 关闭客户端

2.6 套接字函数

(1)服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来
(2)客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
(3)公共用途的套接字函数
s.recv() 接收TCP数据
s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字

2.7 TCP套接字模型二(通信循环)

# (1)服务端
import socket

server = socket.socket()
server.bind(('127.0.0.1', 9000))
server.listen(5)
while True:
    conn, addr = server.accept()  # 用来获取不同的客户端连接对象
    while True:  # 持续的和当前连接好的客户端进行交互
        recv_info = conn.recv(1024)  # 接收客户端的二进制数据
        print(f'对方信息内容为:{recv_info.decode()}')
        send_info = recv_info.decode().upper()  # 收到客户端的小写字母后向客户端返回大写字母
        conn.send(send_info.encode())
# (2)客户端
import socket

client = socket.socket()
client.connect(('127.0.0.1', 9000))  # 连接服务端ip和端口,在这个例子中不写客户端ip和端口也行,只要有对方的就能进行通信
while True:
    send_info = input('请输入给服务端的数据:')
    client.send(send_info.encode())
    recv_info = client.recv(1024)
    print(f'对方回复信息内容为:{recv_info.decode()}')

 

标签:info,25,socket,server,粘包,client,接字,客户端,Socket
From: https://www.cnblogs.com/hbutmeng/p/18383355

相关文章

  • Linux网络:TCP & UDP socket
    Linux网络:TCP&UDPsocketsocket套接字sockaddr网络字节序IP地址转换bzeroUDPsocketsocketbindrecvfromsendtoTCPsocketsocketbindlistenconnectacceptsendrecv本博客讲解Linux下的TCP和UDP套接字编程。无论是创建套接字、绑定地址,还是发送和接收数据,......
  • .NET周刊【8月第4期 2024-08-25】
    国内文章从控制台开始关联Win2D和WinUI3应用https://www.cnblogs.com/lindexi/p/18378612本文将告诉大家如何从最简单的控制台开始搭建,让Win2D和WinUI3关联起来,让Win2D可以将内容渲染到WinUI3应用上。为何Thread.Sleep半毫秒和一毫秒等待时间差距如此之大h......
  • 软设每日一练1——(16进制快速算结果)若用256K×8bit存储器芯片,构成地址40000000H到400F
    题目:若用256K× 8bit的存储器芯片,构成地址40000000H到400FFFFFH且按字节编址的内存区域,则需(        )片芯片A.4        B.8        C.16        D.32        答案:A解:1、首先看单位,存储器芯片单位是256K× 8bit,地址是字节......
  • Websocket
    一、基础知识全双工、半双工和单工是通信系统中的三种数据传输模式,它们描述了数据在通信链路上的传输方式和方向。全双工:数据可以同时在两个方向传输,双方可以同时发送和接收数据。这是双向通信最先进的模式,允许同时进行的双向交流。半双工:数据可以在两个方向上传输,但不能同时......
  • zabbix“专家坐诊”第253期问答
    问题一Q:目前zabbix是不是没有针对监控项或者自动发现规则的“进行检查”的API?A:按照我这边了解的可能是没有的。 问题二Q:这个怎么改 改后重启server找到这个对应的监控,测试看看返回值有没有减少 Q:我试试看,之前是我看错问题了 问题三Q:用官方的vmware模板监控vcent......
  • 【2024-08-25】连岳摘抄
    23:59你是中国人吗?你爱中国吗?你愿意中国好吗?                                                 ——张伯苓很多人看不上全职主妇,或全职主夫,以为这是丧失独立性,书白读......
  • 从Flow小白到专家,Winter '25让流程自动化更简单!
    Salesforce平台每月提供超过1万亿次自动化服务,每月可节省超1090亿小时,预计为客户创造超2万亿美元的商业价值。这是一组不可思议的数字,充分展现了软件自动化的力量。Flow是整个Salesforce平台自动化的未来,一直在将大量资源用于开发Flow创新。本次Winter'25中自然也少不了Flow的......
  • 【实践经验】端口被占用问题:listen tcp:bind:only one usage of each socket address
    文章目录一.问题描述二.分析1.适用错误三.解决方法1.打开控制台2.查看端口的使用情况2.1不知道端口号——查看所有运行的端口2.2知道端口号3.查看使用进程的程序4.杀死进程5.验证端口是否释放一.问题描述goland启动项目后报错:“listentcp:bind:onl......
  • P5250 【深基17.例5】木材仓库
    【深基17.例5】木材仓库题目描述博艾市有一个木材仓库,里面可以存储各种长度的木材,但是保证没有两个木材的长度是相同的。作为仓库负责人,你有时候会进货,有时候会出货,因此需要维护这个库存。有不超过100000条的操作:进货,格式1Length:在仓库中放入一根长度为Length(不超过$10^......
  • Luogu P7250 BalticOI 山峰 题解 [ 蓝 ] [ 模拟 ] [ 并查集 ] [ BFS ]
    LuoguP7250BalticOI山峰。一道大模拟,很暴力,也很难写。建议紫或蓝,标签为模拟、广度优先搜索、并查集。思路首先观察到答案取决于路线上的最低点,所以我们可以把所有点的高度丢进一个桶里,从大到小枚举,尝试更新答案。这应该是个挺经典的trick了。感性理解可以看作所有山都先......