首页 > 其他分享 >socket通信中所说的粘包是什么?

socket通信中所说的粘包是什么?

时间:2023-04-26 15:23:26浏览次数:49  
标签:包是 socket 数据包 length client 所说 长度 data

粘包是指在使用TCP协议传输数据时,发送方发送的多个数据包在接收方可能会被连续接收,从而导致多个数据包粘在一起。这是因为TCP协议保证了数据的可靠性和顺序,但并不保证边界。粘包问题在应用层需要特殊处理,否则可能导致接收方无法正确解析传输的数据。

以下是处理粘包问题的一些建议:

  1. 固定长度的数据包:如果每个数据包的大小都是固定的,那么接收方可以按照固定长度进行解析,从而避免粘包问题。

  2. 添加消息边界标志:为每个数据包添加特殊的边界标志,例如换行符("\n")或其他自定义字符。接收方收到数据后根据边界标志拆分数据包。

  3. 在数据包前加上长度信息:在发送方发送数据包前,先发送一个表示数据包长度的包头,这样接收方就能知道要读取多少字节的数据。例如,在发送实际数据之前,先发送一个4字节的整数,表示实际数据的长度。

  4. 使用定长包头与可变长度数据组合:将包头设计成固定长度,包头中包含实际数据的长度信息。这样接收方首先读取固定长度的包头,解析出实际数据的长度,然后再读取相应长度的数据。这种方法在许多应用协议中都被广泛采用。

以下是一个使用Python实现的在数据包前加上长度信息的TCP Socket通信示例:

服务器端代码:

import socket
import struct

def recvall(sock, n):
    data = bytearray()
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            return None
        data.extend(packet)
    return data

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 12345))
server_socket.listen(1)

print("等待客户端连接...")
client_socket, client_addr = server_socket.accept()
print("客户端已连接:", client_addr)

length_data = recvall(client_socket, 4)
if length_data:
    length = struct.unpack('>I', length_data)[0]
    data = recvall(client_socket, length)
    print("接收到数据:", data.decode())

response = "你好,我是服务器!"
encoded_response = response.encode()
client_socket.send(struct.pack('>I', len(encoded_response)) + encoded_response)

client_socket.close()
server_socket.close()

客户端代码:

import socket
import struct

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 12345))

message = "你好,我是客户端!"
encoded_message = message.encode()
client_socket.send(struct.pack('>I', len(encoded_message)) + encoded_message)

length_data = client_socket.recv(4)
if length_data:
    length = struct.unpack('>I', length_data)[0]
    data = bytearray()
    while len(data) < length:
        packet = client_socket.recv(length - len(data))
        if not packet:
            break
        data.extend(packet)
    print("接收到数据:", data.decode())

client_socket.close()

在这个示例中,我们在发送实际数据前,先发送一个4字节的整数(网络字节序)表示数据的长度。接收方首先读取4字节的长度信息,然后根据长度读取相应的数据,从而避免了粘包问题。

标签:包是,socket,数据包,length,client,所说,长度,data
From: https://www.cnblogs.com/zhao-jie-li/p/17356186.html

相关文章

  • Python的socket编程
    目前处在学习python爬虫的阶段,昨天看到了python的socket模块,分别实现TCP、UDP时间戳回显。1、tcp通信server和client代码#tcpServer.py#!/usr/bin/python#-*-coding:utf-8-*-fromsocketimport*fromtimeimportctimeHOST=''PORT=21156BUFSIZE=1024ADD......
  • 最全的WebSocket协议分析
    0实时跟服务端通信方案1轮询:客户端向服务端无限循环发送http请求,一旦服务端有最新消息,从当次http响应中带回,客户端就能收到变化2长轮回(web版微信采用此方式)客户端和服务端保持一个长连接(http),等服务端有消息返回就断开,如果没有消息,就会hold住,等待一定时间,然后再重新连接,也......
  • C# Socket入门
    1.什么是Socketsocket被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过socket这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据;套接字就是四元组,即源ip+端口port目的ip+端口port,表示绝对唯一的连接;Socket是在应用层(Http、SSH......
  • 轮询、长轮询和websocket
    轮询从字面意思理解,轮询是不断的询问服务器然后获取资源的一种方式,可以解决像多次TCP连接造成的服务器堵塞(但是多次发送http请求也会浪费服务器资源)。长轮询长轮询是轮询的一种变种,我理解的是轮询相当于是每隔一个时间去发送http请求询问数据,长轮询会根据情况去决定间隔的时......
  • docker.sock 和 docker.socket 无操作权限的修复
     问题:第三软件jenkins等,甚至docker本身都有可能报如下无权限操作的错误:docker:GotpermissiondeniedwhiletryingtoconnecttotheDockerdaemonsocketatunix:///var/run/docker.sock:Posthttp://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/create:dialuni......
  • ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run
      今天执行mysql操作的时候出现了错误:ERROR2002(HY000):Can'tconnecttolocalMySQLserverthroughsocket'/var/run/mysqld/mysqld.sock'问题1:首先检查是否安装了mysql-server了 sudoapt-getinstallmysql-servertoinstallmysqlonubuntu  sudoapt-getin......
  • websocket与C# socket相互通信
    web端代码就是js代码,C#有两种方式:使用第三方库,如Fleck,使用C#原生socket编程实现 web端:<!doctypehtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>下发网站上文件到学生机</title><scripttype=......
  • #yyds干货盘点#区别WebSocket 与 Socket
    WebSocket是什么WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocketAPI中,浏览器和服务器只需要完成一次HTTP握手,两者之间就直接可以创建持久性的连接,并进行双向数......
  • supersocket新的配置属性 "textEncoding"
    supersocket新的配置属性"textEncoding" 在SuperSocket1.6之前的版本,当你通过Session对象发送文本时,将文本信息转换成能够通过Socket传输的二进制数据的默认编码是UTF8。你可以通过设置Session的Charset属性来修改这个编码。现在在SuperSocket1.6中,你......
  • Java WebSocket客户端
    https://www.cnblogs.com/SjhCode/p/WebSocketClient.html注意事项:1.@Scheduled(fixedDelay=5000)2.心跳检测3.导入依赖与导包<dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.......