0

我正在尝试使用System.Net.SocketsTcpClient类在 C# 中为我的游戏编写网络部分。

  • 每个更新服务器都向客户端发送信息。
  • 所有信息都内置在 2kb 数据包中,因此在 1 次更新中可以发送 1-2-3-5-10 个数据包。
  • 客户正在检查信息,如果信息格式正确 - 然后阅读它。
  • 一切正常,直到服务器开始尝试发送太多数据包。
  • 当它发生时,客户端通常会收到 20-50 个数据包中的错误数据 1 的数据包。
  • 例如,1 次更新的 1-2 个数据包通常可以正常接收,3-10 个更新数据包会给出错误的数据流。
  • 如果我在 1 次启动多个客户端,那应该从服务器获得相同的数据流 - 它们获得不同数量的成功和失败数据流。

我做错了什么,我该如何逃避这个错误的数据流?

我只是在 1 毫秒内发送了太多数据,并且需要随着时间的推移发送它吗?

这是发送信息:

TcpClient client;

public void SendData(byte[] b)
    {
        //Try to send the data.  If an exception is thrown, disconnect the client
        try
        {
            lock (client.GetStream())
            {
                client.GetStream().BeginWrite(b, 0, b.Length, null, null);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

这是接收信息:

byte[] readBuffer;
int byfferSize = 2048;

private void StartListening()
    {
        client.GetStream().BeginRead(readBuffer, 0, bufferSize, StreamReceived, null);
    }

    private void StreamReceived(IAsyncResult ar)
    {
        int bytesRead = 0;
        try
        {
            lock (client.GetStream())
            {
                bytesRead = client.GetStream().EndRead(ar); // просмотр длины сообщения
            }
        }
        catch (Exception ex)
        { MessageBox.Show(ex.Message); }

        //An error happened that created bad data
        if (bytesRead == 0)
        {
            Disconnect();
            return;
        }

        //Create the byte array with the number of bytes read
        byte[] data = new byte[bytesRead];

        //Populate the array
        for (int i = 0; i < bytesRead; i++)
            data[i] = readBuffer[i];

        //Listen for new data
        StartListening();

        //Call all delegates
        if (DataReceived != null)
            DataReceived(this, data);
    }

它是主要的网络代码。

4

1 回答 1

2

我不知道您收到数据后如何处理数据,但很可能您没有从连接中读取所有数据。你有:

bytesRead = client.GetStream().EndRead(ar);

无法保证您读取的字节数是服务器发送的所有字节数。例如,服务器可以发送 2,048 个字节,但是当您调用 时Read,只有 1,024 个字节可用。其余的仍处于“运输途中”。正如NetworkStream.Read 的文档所说:

Read 操作读取尽可能多的可用数据,最多为 size 参数指定的字节数

您可能会收到部分数据包。如果您的DataReceived处理程序假设data缓冲区包含完整的数据包,那么您将遇到问题。

要可靠地从网络流中读取,您需要知道应该读取多少数据,或者您需要一个记录分隔符。如果您期待一个完整的数据包,则必须确保在尝试处理它之前获得一个完整的数据包。您的代码只是检查是否bytesRead不为 0。如果是其他任何内容,您只需将其传递。DataReceived除非您的处理程序知道如何缓冲部分数据包,否则这将是一个问题。

另一方面,您确实不需要锁定网络流。除非您可以有多个线程从同一个流中读取。那将是灾难性的。扔掉锁。你不需要它。

于 2013-07-25T16:41:57.627 回答