异步 TCPClient C# 消息未发送

本文关键字:消息 TCPClient 异步 | 更新日期: 2023-09-27 17:55:15

基本上我需要的是p2p连接,现在我有一个异步服务器和客户端,它通过TcpClient s相互通信。 问题是服务器很少检测到传入的消息,通常只接收第一条消息。我的服务器代码在这里:

    public void RecieveAsync()
    {
        if (netStream == null) netStream = Server.GetStream();
        netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream);
    }

    public void recieveCallBack(IAsyncResult ar)
    {
        //try
        //{
        int rec = netStream.EndRead(ar);
        if (rec == 0)
        {
            if (Disconnected != null)
            {
                Disconnected(this);
                return;
            }
        }
        else
        {
            if (DataRecieved != null)
            {
                string RecievedData = Encoding.ASCII.GetString(ReadBuffer, 0, rec);
                DataRecieved(RecievedData);
            }
            ReadBuffer = new byte[1024];
        }
    }

并且发送数据的客户端代码在这里(它被包装成一个while循环,用Thread.Sleep(1)一遍又一遍地发送数据,以更新玩家位置)

    public void Send(byte[] data, int index, int length)
    {
        //add data as state
        //socket.NoDelay = true;
        Buffer.BlockCopy(data, 0, writeBuffer, index, length);
        if (netStream == null) netStream = TcpClient.GetStream();
        netStream.BeginWrite(writeBuffer, 0, writeBuffer.Length, sendCallback, netStream);

    }
    private void sendCallback(IAsyncResult ar)
    {
        //try
        //{
           netStream.EndWrite(ar);
            //if (ar.AsyncState != null)
            //{
            //    byte[] buffer = (byte[])ar.AsyncState;
            //    socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, sendCallback, null);
            //    return;
            //}
            if (OnSend != null)
            {
                OnSend(this);
            }
        //catch (Exception ex)
        //{
        //    System.Windows.Forms.MessageBox.Show(ex.ToString());
        //    return;
        //}
    }

默认缓冲区大小为 1024,仅当 netStream.DataAvailible 为 true 时才调用 RecieveAsync,这会在服务器循环中不断检查。

编辑::

这是调用服务器的代码

            while (true)
            {
                byte[] playerData = NormalText(PreparePlayerData());
                server.Send(playerData, 0, playerData.Length);
                if (server.Server.Connected)
                {
                    server.netStream = server.Server.GetStream();
                    while (server.netStream.DataAvailable)
                    {
                        server.RecieveAsync();
                        server.netStream = server.Server.GetStream();
                    }
                }

                Thread.Sleep(1);
            }

异步 TCPClient C# 消息未发送

在网络编程方面,了解各种方法背后发生了什么会有所帮助。对于接收方法,您可以使用

netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream);

这将在收到数据时触发 recieveCallBack(),但下一行是它开始变得有趣的地方。还值得注意的是,对netStream.BeginRead的一次调用只会触发一次回调。如果要继续侦听数据,则需要再次调用netStream.BeginRead。

string RecievedData = Encoding.ASCII.GetString(ReadBuffer, 0, rec);

该框架不保证您将收到您在发送中写入的所有数据。收到一些数据后,您需要决定它,然后再尝试将其转换回字符串。如果您没有收到再次拨打电话所需的一切

netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream);

然后等待更多。

这是编程的一个棘手方面,但你显然正在前进。如果它有助于从工作示例向后工作,请查看方法IncomingTCPPacketHandler()(相当于您的recieveCallBack方法),它来自开源网络库 networkcomms.net。