首页 > 解决方案 > 是否有推荐用于多线程通信而不会丢失数据的流类型?

问题描述

我有一个将 c# (unity) 与 python 连接起来的客户端服务器架构。我需要在 c# 上启动多个线程(多个连接),这些线程将接收一些将从 python 服务器反序列化的数据。

client(c# unity3d) -> c# 中的 6 个线程将接收来自 6 个进程的数据,这些进程将提供来自 python 的数据,这些数据将被反序列化。

经过一些调试后,我设法看到包是从 python 服务器以良好的方式发送的。

然而,在 c# 上,不同线程上的包要么数据太少,要么数据太多。我的假设是来自不同线程的套接字在接收数据时会产生干扰。

连接器的 C# 代码

public class Connector
{
public string ip = "127.0.0.1";

int bytesRead;
IPAddress ipAddress;
IPHostEntry ipHostInfo;

Socket sender;

int bytesRec;

[SerializeField]
private int dataOut;
public Connector() { }
public void establishConnection(int port)
{
    ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
    ipAddress = ipHostInfo.AddressList[0];
    sender = new Socket(ipAddress.AddressFamily,
         SocketType.Stream, ProtocolType.Tcp);

    sender.Connect(ip,port);
}


public void Send(byte[] input) {
    int bytesSent = sender.Send(input);

}

public byte[] Receive(int index) {

    byte[] bytesToRead = new byte[1024 * 1024 * 60];
    Array.Clear(bytesToRead, 0, bytesToRead.Length);

    try
    {
        bytesRec = sender.Receive(bytesToRead);
        Array.Resize(ref bytesToRead, bytesRec);
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }

    if (bytesRec != 0)
    {
        return bytesToRead;
    }
    else
    {
        return null;
    }
}
}

在 main 中,我启动 5 个线程,如下所示:

for (int x = 1; x <= 4; x++)
    {
        new ThreadComponent(x, this, featureMapCreator).init();
    }

线程组件初始化连接并执行接收部分

  Connector socketConnector = new Connector();
    socketConnector.establishConnection(60000 + index); // index are from 1 to 4
  while (true)
     {
            doLogicGetData(socketConnector);

     }
 In doLogicGetData the receive is called
 byte[] z = socketConnector.Receive(index);

我也尝试使用带有网络流的 TcpClient,但结果是一样的。

我正在寻找的是一个流/套接字,它有利于在按顺序读取所有数据的多线程环境中的本地机器上进行通信。目前,此实现并未始终提供所有数据。

标签: c#multithreadingunity3dclientclient-server

解决方案


我建议您为六 (6) 个进程线程分配一个唯一的端口号。这应该可以防止“不同的线程在接收数据时相互干扰。”。

此外,您可能不会在一次获取中接收到所有传输的数据。数据传输可以分成多个数据包,这些数据包可能需要多次获取才能完成单个传输数据流。每个数据传输都应该有某种方式来标记传输的结束,以便 get 循环可以告诉何时停止获取数据来处理传输。


推荐阅读