python 简单的解决一下粘包问题

粘包问题可能发生在数据量很小的情况下,经过底层算法的优化,就把几条很小的数据合并发送了。只会发生在TCP的情况下,UDP一般不会。
那么如何解决呢?
度娘们给我的回答都能一致,大致的思路就是设置一个数据长度的标志位,并且都是要求占4个字节,有的是说数据标志位和数据一起发送,有的说是先发送标志位,然后紧接着接收数据,害,我感觉都一样。
如果先发送标志位的话,额,倒也是可以,首先直接设定接收4个字节的数据,然后byte转为数字,再次接收真实数据。

如下:注释应该是写的比较清楚了
python 2.*服务端

# coding=utf-8
# 使用utf-8编码
import socket
import select
import struct

# the max player number
playerNumber = 10

# host and port
host = socket.gethostname()
port = 12345

# create socket named mySocket,based on TCP
mySocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# bind
mySocket.bind(("127.0.0.1",port))

# listen
mySocket.listen(playerNumber)

Socket_List = [mySocket]

while True:

    myEvent,wret,xret = select.select(Socket_List,[],[])
    # print myEvent
    for i in myEvent:
        if i is mySocket:
            conn,addr = i.accept()
            Socket_List.append(conn)
        else:
            # 接收到消息,输出
            try:
                receiveData = i.recv(4)
                # 这里是将byte转为整数
                data = struct.unpack('i',receiveData)
                print type(data[0]),data[0]
                receiveData = i.recv(data[0])
                print receiveData
                # 铭记,客户端正常关闭的话
                # 这里直接判断接收的是否为空字符串即可
                # if receiveData == "88" or receiveData == "":
                if receiveData == "":
                    Socket_List.remove(i)
                    i.close()
                    continue
            # 客户端关闭了,从sockelist中删除
            except:
                Socket_List.remove(i)
                i.close()
                continue

Socket_List.remove(mySocket)
mySocket.close()

配套C#客户端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace TCP客户端
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建socket
            Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //链接
            mySocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345));
            for (int i = 0; i < 200; i++)
                mySocket.Send(MessageUtil.GetBytes(i.ToString()));

            mySocket.Close();
        }
    }
}

配套的MessageUtil类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TCP客户端
{
    class MessageUtil
    {
        public static byte[] GetBytes(string message)
        {
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            int messageLength = messageBytes.Length;
            //将长度变为byte数组
            byte[] messageLengthBytes = BitConverter.GetBytes(messageLength);
            byte[] resultBytes = messageLengthBytes.Concat(messageBytes).ToArray();
            return resultBytes;
        }
    }
}

执行效果,没有粘包现象发生
在这里插入图片描述

不错处理的话,可以发现,即使就200次循环,还是有很多粘包发生
在这里插入图片描述

发布了201 篇原创文章 · 获赞 210 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40666620/article/details/104874282