TcpClient缺少数据

时间:2013-07-25 15:48:12

标签: c# tcpclient

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

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

我做错了什么,如何规避错误的数据流呢?

我只是在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);
    }

这是主要的网络代码。

1 个答案:

答案 0 :(得分:2)

收到数据后,我不知道您对数据做了什么,但很可能您没有从连接中读取所有数据。你有:

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

无法保证您读取的字节数是服务器发送的所有字节数。例如,服务器可能发送了2,048个字节,但是当您调用Read时,只有1,024个字节可用。其余的人仍然“在途中”。正如documentation for NetworkStream.Read所说:

  

Read操作读取尽可能多的数据,最多为size参数

指定的字节数

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

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

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