gpt4 book ai didi

c# - 如果发送了很多消息,如何写入 MemoryStream

转载 作者:可可西里 更新时间:2023-11-01 02:50:27 25 4
gpt4 key购买 nike

下面是我现在如何从我的流中读取数据:

public List<ServerClient> clients = new List<ServerClient>();

while (true)
{
Update();
}

private void Update()
{
//Console.WriteLine("Call");
if (!serverStarted)
{
return;
}

foreach (ServerClient c in clients.ToList())
{
// Is the client still connected?
if (!IsConnected(c.tcp))
{
c.tcp.Close();
disconnectList.Add(c);
Console.WriteLine(c.connectionId + " has disconnected.");
CharacterLogout(c.connectionId);
continue;
//Console.WriteLine("Check for connection?\n");
}
else
{



// Check for message from Client.
NetworkStream s = c.tcp.GetStream();
if (s.DataAvailable)
{
string data = c.streamReader.ReadLine();

if (data != null)
{
OnIncomingData(c, data);
}

}
//continue;
}
}

for (int i = 0; i < disconnectList.Count - 1; i++)
{
clients.Remove(disconnectList[i]);
disconnectList.RemoveAt(i);
}


}

当读取数据时,它被发送到处理数据的 OnIncomingData 函数。我在那里没有问题。

下面是我如何将数据发送到流:

public void Send(字符串头,字典数据){

if (stream.CanRead)
{
socketReady = true;
}

if (!socketReady)
{
return;
}
JsonData SendData = new JsonData();
SendData.header = "1x" + header;
foreach (var item in data)
{
SendData.data.Add(item.Key.ToString(), item.Value.ToString());
}
SendData.connectionId = connectionId;

string json = JsonConvert.SerializeObject(SendData);
var howManyBytes = json.Length * sizeof(Char);
writer.WriteLine(json);
writer.Flush();

Debug.Log("Client World:" + json);

这是我的:

public class ServerClient
{
public TcpClient tcp;
public int accountId;
public StreamReader streamReader;
public int connectionId;
public ServerClient(TcpClient clientSocket)
{
tcp = clientSocket;
}
}

这是我的 OnConnection 函数:

    private void OnConnection(IAsyncResult ar)
{
connectionIncrementor++;
TcpListener listener = (TcpListener)ar.AsyncState;
NetworkStream s = clients[clients.Count - 1].tcp.GetStream();
clients.Add(new ServerClient(listener.EndAcceptTcpClient(ar)));
clients[clients.Count - 1].connectionId = connectionIncrementor;
clients[clients.Count - 1].streamReader = new StreamReader(s, true);
StartListening();


//Send a message to everyone, say someone has connected!
Dictionary<string, string> SendDataBroadcast = new Dictionary<string, string>();
SendDataBroadcast.Add("connectionId", clients[clients.Count - 1].connectionId.ToString());

Broadcast("001", SendDataBroadcast, clients, clients[clients.Count - 1].connectionId);
Console.WriteLine(clients[clients.Count - 1].connectionId + " has connected.");
}

通常一切正常。但是,如果我尝试每 1 秒发送更多请求,就会出现问题。收到的消息不完整。它只接收发送的消息的一部分。

Debug.Log("Client World:"+ json); 我可以看到消息是完整且完整的,但在服务器上我看到它不是。

如果我发送较少的请求,就不会发生这种情况。

因此,出于这个原因,我认为我应该创建一个 MemoryStream 并将一条消息放在那里,然后再阅读它。但是我真的不确定我该怎么做。你能帮忙吗?

最佳答案

整个代码不是很好,但我会专注于您的具体问题。这很可能与 StreamReader 的数据缓冲有关。 StreamReader 的缓冲区大小(您可以将其传递给构造函数)默认为 1024 字节。当您调用 ReadLine 时 - 流读取器完全有可能从底层流中读取行。在你的情况下 - 你有 while 循环,在其中枚举连接的客户端,并且在循环的每次迭代中你创建新的 StreamReader 并从中读取一行。当消息率低时 - 一切看起来都很好,因为在你的循环迭代之间只有一行到达。现在假设客户端快速发送了 2 条 json 消息,每条 800 字节,并且它们都到达了您的套接字。现在调用 StreamReader.ReadLine。因为缓冲区大小是 1024 - 它将从套接字 (NetworkStream) 读取 1024 字节并返回前 800 字节给你(作为一行)。您处理该行并丢弃 StreamReader 以进入 while 循环的下一次迭代。通过这样做,您还丢弃了部分消息(下一条消息的 224 字节),因为它们已经从套接字读取到 StreamReader 缓冲区中。我认为应该清楚如何解决这个问题 - 不要每次都创建新的 StreamReader 而是为每个客户端创建一个(例如存储为 ServerClient 的成员) 并使用它。

关于c# - 如果发送了很多消息,如何写入 MemoryStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47386798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com