Python Socket 套接字通信基础与粘包问题解析

Hazel
Hazel
发布时间:2026-10-13 | 6人浏览过
原创

本文详细解析Python中Socket套接字的原理与实现,涵盖基于TCP协议的简单通信代码示例。重点探讨了阻塞模式下的同步问题、数据发送非空判断以及接收超过1024字节时的粘包现象,并结合subprocess模块实现服务端命令响应机制,为后续解决粘包问题奠定基础。

Socket概念与原理

首先介绍Socket的概念。

Socket在操作系统架构中位于应用层与传输层之间,属于一种抽象接口。它提供了一组相对简单的操作方式,主要用于接收数据,并将接收到的数据传递给操作系统处理。

既然可以直接与操作系统交互,为何还需要Socket?这种想法存在误区。

操作系统的底层接口实际上非常复杂且难以直接使用。如果开发者直接通过操作系统接口进行数据交换,过程将极其繁琐。因此,开发者需要一种中间机制来简化这一过程,Socket(套接字)应运而生。它的核心作用是对操作系统间的数据交换进行高度封装和简化,从而降低开发难度。

Python Socket基础通信实现

利用Socket可以实现基础的通信功能。

Python内置了socket模块,利用该模块可以方便地实现基于TCP协议的简单通信。


 #基于切换连接的循环通信
 import socket #首先我们在文件中导入socket 模块
 phone = socket.socket() #实例化一个对象
 phone.bind(('127.0.01',8765))#bind是存放ip地址的(这里存放的是本地的IP地址)
 phone.listen(5)#可以设置连接的个数,
 while 1:#循环等待连接
  conn,adds = phone.accept()
  while 1:#要循环聊天我们要重复接收发送
   try: #异常处理
    receives_commands = conn.recv(1024) #接收命令请求,最多接收1024字节当然你也可以调整
    receivse_commands = receives_commands.decode('utf-8')#网络传输是以字节的形势的所以我们要进行解码
    print(f'来自客户端的消息{receives_commands}') #打印消息
    if receives_commands.upper(0 == 'Q':break #正常结束
    dispatch_orders = inport('请输入:').strip().encode('utf-8')
    conn.send(dispatch_orders)
   except ConnectionResetError:#客户端异常结束
    print('客户端终端')
    break
  conn.close() #关闭连接
 phone.close#关闭服务端
 #客户端
 import socket
 phone = socket.socket()
 phone.connect(('127.0.01',8765))  #连接服务端地址   
 while 1:     
  dispatch_orders = inport('请输入:').strip().encode('utf-8')#发送请求
  if not dispatch_orders:print('不能为空')#不能为空
  phone.send(dispatch_orders)  #发送      
  if dispatch_orders.upper() ==b'Q':#正常退出
   break
  receives_commands = phone.recv(1024)#接收服务端的回执
  receives_commands = receives_commands.decode('utf-8')#解码
  print(f'来自客户端的消息{receives_commands}') #打印        
 phone.close()#关闭客户端

接下来,我们将通过Socket构建一个简单的通信链接循环。

通信中的阻塞与非空处理

在实现过程中,有几个关键点需要注意。

首先是阻塞问题。当服务器和客户端均处于阻塞模式时,accept和recv操作会导致双方同步等待,即一方发送或接收时另一方必须同步响应,否则程序会陷入静止状态。这种同步阻塞机制在逻辑上是不合理的,可能导致程序行为异常。

其次,在设计通信逻辑时,必须确保发送的数据不为空。如果发送内容为空,服务端将无法接收到有效消息。因此,代码中需要加入非空判断逻辑。此外,当接收到的数据超过1024字节时,会出现何种情况?

粘包现象与subprocess模块应用

下面针对上述问题进行解答。

为此,我们需要引入操作系统相关的模块。

在Python中,subprocess模块专门用于与cmd命令行进行交互。


 obj = subprocess.Popen('dir',#实例化对象括号内第一个参数就是我们的cmd命令行的命令,这里我们写的是dir显示文件夹中内容
         shell=True,
         stdout=subprocess.PIPE,
         stderr=subprocess.PIPE,
         )
   print(obj.stdout.read().decode('gbk')) # 正确命令
   print(obj.stderr.read().decode('gbk')) # 错误命令

基于此,我们可以构建一个服务端响应客户端命令的机制。


import socket
import subprocess
phone = socket.socket()
phone.bind(('127.0.01',8695))
phone.listen(5)
while 1:
 conn,adds = phone.accept()
 while 1:
  try:
   receives_commands = conn.recv(1024)
   if receiver_commands ==b'Q':break 
   #obj = subprocess.Popen(Receiving_instructiors,
         # shell= True,
       #stdout = subprocess.PIPE,
       #stderr = subprocess.PIPE
         )
  obj = subprocess.Popen(receives_commands.decode('utf-8')#动态的传入命令
       shell = True
       stdout = subprocess.PIPE
       stderr = subprocess.PIPE 
       )
 # print(obj.stdout.read().decode('gbk')) # 正确命令
 # print(obj.stderr.read().decode('gbk')) # 错误命令
  ret = obj.stodut.read()+obj.stderr.read()#将产生的内容进行拼接
  conn.send(ret)
 except ConnectionResetError:
   print('客户端终端')
   break 
 conn.close()
phone.close()
import socket
phone = socket.socket()
phone.connect(('127.0.01',8695))
while 1:
 dispatch_orders = inport('请输入命令:').strip().encode('utf-8')
 if not dispatch_orders:print('输入不能为空')
 phone.send(dispatch_orders)
 if dispatch_orders.upper() ==b'Q':break
 receives_commands = phone.recv(1024)
 receives_commands = receives_commands.decode('utf-8')
 print(f'来自客户端的消息{receives_commands}')
phone.close()  

然而,这里会出现一个问题:当输入的help命令长度超过1024字节时,该如何处理?

另一个问题是,当输入下一条命令时,可能会接收到上一条命令未传输完成的部分数据,这种现象被称为“粘包”。

那么,造成粘包的原因是什么?

如何解决粘包问题?

这些问题的具体解决方案将在后续章节中详细讲解。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表