一. 前言

在网络编程中,粘包是指TCP协议在传输过程中,多条数据被合并成一条数据发送或者一条数据被拆分成多个数据发送的现象。

二. 粘包问题的常规处理方法:

使用固定长度的包头 可以在发送数据前先发送一个固定长度的包头,包头中包含了数据的长度信息。接收方根据包头中的长度信息来正确地拆分数据。

三. 示例代码

2. 接收方:【server】服务端示例代码

import socket
import struct


def send_message(sock, message):
    # 使用struct将消息长度打包为4字节的二进制数据
    length = len(message)
    sock.send(struct.pack('!I', length))
    # 发送消息内容
    sock.sendall(message)


def recv_message(sock):
    # 接收消息长度
    length_data = recvall(sock, 4)
    length = struct.unpack('!I', length_data)[0]
    # 接收消息内容
    message = recvall(sock, length)
    return message


def recvall(sock, size):
    # 从socket接收指定大小的数据
    data = b''
    while len(data) < size:
        packet = sock.recv(size - len(data))
        if not packet:
            return None
        data += packet
    return data


# 创建TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定到本地地址和端口
server_address = ('localhost', 12345)
sock.bind(server_address)

# 开始监听连接
sock.listen(1)

print('等待客户端连接...')

while True:
    # 等待客户端连接
    client_socket, client_address = sock.accept()
    print('客户端已连接:', client_address)

    try:
        while True:
            # 接收客户端消息
            message = recv_message(client_socket)
            if not message:
                break
            print('接收到消息:', message)

            # 发送回复消息
            reply = '已收到消息:' + message.decode('utf-8')
            send_message(client_socket, reply.encode('utf-8'))
            print('发送回复消息:', reply)
    finally:
        # 关闭连接
        client_socket.close()

在服务端代码中,首先创建一个TCP Socket并绑定到本地地址和端口,然后开始监听连接。当有客户端连接时,创建一个新的Socket与客户端通信。通过循环不断接收客户端发送的消息,并将收到的消息回复给客户端。当客户端关闭连接时,关闭对应的Socket,等待下一个客户端连接。

2. 发送方:【client】客户端示例代码

import socket
import struct
import time


def send_message(sock, message):
    # 使用struct将消息长度打包为4字节的二进制数据
    length = len(message)
    sock.send(struct.pack('!I', length))
    # 发送消息内容
    sock.sendall(message)


def recv_message(sock):
    # 接收消息长度
    length_data = recvall(sock, 4)
    length = struct.unpack('!I', length_data)[0]
    # 接收消息内容
    message = recvall(sock, length)
    return message


def recvall(sock, size):
    # 从socket接收指定大小的数据
    data = b''
    while len(data) < size:
        packet = sock.recv(size - len(data))
        if not packet:
            return None
        data += packet
    return data


# 创建TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务端
server_address = ('localhost', 12345)
sock.connect(server_address)

while True:
    # 发送消息给服务端
    message = 'Hello, Server!'
    send_message(sock, message.encode('utf-8'))
    print('发送消息:', message)

    # 接收服务端回复消息
    reply = recv_message(sock)
    print('接收到回复消息:', reply.decode('utf-8'))
    time.sleep(1)

运行结果
Python - 【Socket】消息粘包处理demo(一)-LMLPHP
在客户端代码中,首先创建一个TCP Socket并连接到服务端。然后发送一条消息给服务端,并接收服务端的回复消息。

四. 总结

需要注意的是,这个代码示例只是演示了如何处理消息粘包的问题,它并不考虑错误处理和异常情况。在实际应用中,需要根据具体需求添加适当的错误处理和异常处理代码。

以上就是关于Python - 【socket】粘包常见的一种方法处理,后续有时间会在介绍另一种方法。希望文章对你有所帮助。

01-24 02:09