0

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

    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,RecieveAsync仅在netStream.DataAvailible为 true 时调用,在服务器循环中不断检查。

编辑 ::

这是调用服务器的代码

            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);

            }
4

1 回答 1

1

当涉及到网络编程时,了解各种方法背后发生了什么是有帮助的。对于您的接收方法,您使用正确配置回调

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);

然后等待更多。

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

于 2013-01-23T15:35:25.653 回答