Java 为什么BinaryReader在线程内,从netty读取错误的数据包?

Java 为什么BinaryReader在线程内,从netty读取错误的数据包?,java,c#,sockets,unity3d,netty,Java,C#,Sockets,Unity3d,Netty,我将数据从netty发送到unity 3d游戏引擎中的一个c应用程序,在那里它读取数据包id并根据线程中的数据包id执行不同的方法,BinaryReader读取的数据包id是错误的,我无法理解为什么 以下是custombuffer、datainputstream和dataoutputstream的类: 你不必仔细阅读,我把它们贴在网上,这样你就知道它们是什么了 这是登录方法 public void SendLogin(string username,string password) {

我将数据从netty发送到unity 3d游戏引擎中的一个c应用程序,在那里它读取数据包id并根据线程中的数据包id执行不同的方法,BinaryReader读取的数据包id是错误的,我无法理解为什么

以下是custombuffer、datainputstream和dataoutputstream的类:

你不必仔细阅读,我把它们贴在网上,这样你就知道它们是什么了

这是登录方法

public void SendLogin(string username,string password)
{
    Debug.Log ("Sending username and password");
    CustomBuffer buffer = new CustomBuffer (ClientOutput);
    buffer.WriteUTF (username);
    buffer.WriteUTF (password);
    buffer.SendBuffer ();
}
下面是sendLogin的服务器处理程序

    public PacketEncoder sendLogin(boolean value, Account account,byte opcode) {

    ChannelBuffer buffer = new DynamicChannelBuffer(2);
    ChannelBufferOutputStream out = new ChannelBufferOutputStream(buffer);
    try {
        out.writeInt(0);
        out.writeBoolean(value);
        System.out.println("sendig login back packet 0");
        if(value) {
            System.out.println("value true sending username");
            out.writeUTF(account.getUsername());
        }

        else if(!value) {
            System.out.println("value false sending opcode : "+ String.valueOf( (int)opcode));
            out.writeByte(opcode);
        }

        Send(out.buffer());
        out.close();

    } catch(IOException e) {

        e.printStackTrace();
    }


    return this;
}
在这里它工作正常!下面是问题

这是在角色创建请求后发送回信息的netty方法

public PacketEncoder SendCharacterCreationResult(boolean exists,boolean success) {
        ChannelBuffer buffer = new DynamicChannelBuffer(2);
        ChannelBufferOutputStream out = new ChannelBufferOutputStream(buffer);
        try {
            out.writeInt(2);
            out.writeBoolean(exists);
            out.writeBoolean(success);

            //debug console 
            System.out.println(" ");
            System.out.println("Sending Character Creation Result packet : 2");
            System.out.println("exists : " + String.valueOf(exists));
            System.out.println("success : " + String.valueOf(success));

            Send(out.buffer());
            out.close();
        } catch(IOException e)
        {
            e.printStackTrace();
        }

        return this;
    }
这是来自c的数据包处理程序

    void InputLoop()
    {
        while(Client.Connected)
        {
            int packetID = ClientInput.ReadInt();
            Debug.Log("packedID : " + packetID);
            switch(packetID)
            {
            case 0: //Login
                PacketsIn.Login();
                break;
            case 1://Character Request Response
                PacketsIn.CharacterRequest();
                break;
            case 2: //Character Creation Response
                PacketsIn.CharacterCreate();
                break;
            }
        }
    }
登录后,其Perfectly服务器发送数据包id为2的字符创建结果,当它首先到达客户端时,它将运行packetsIn.login,即数据包id为0的数据包和SendCharacterCreationResult中的writeInt2 从下面的方法读取,其中byte opcode=ClientInput.ReadByte; 等于2,我像这样尝试int-opcode=clientInput.ReadInt;它给出了同样的结果。如果我把你搞糊涂了,告诉我在文本中添加完整的文件

这是在线程中运行的inputloop中案例0的函数

public void Login()
{
    bool success = ClientInput.ReadBoolean ();
    if(success)
    {
        string username = ClientInput.ReadUTF();
        Debug.Log("Successfuly Logged In. " + username);
        MasterClient.singleton.ChangeScene(4);
    }
    byte opcode = ClientInput.ReadByte ();
    //GameObject.Find ("MessageLogsText").GetComponent<UILabel> ().text
        Debug.Log( GetLoginMessage (opcode) );
}

private string GetLoginMessage(byte opcode)
{
    switch(opcode)
    {
    case 0:
        return "Invalid Usarename Or Password";
    case 1:
        return "Account Is Already Logged In";
    case 2:
        return "test";
    default:
        return "Invalid opcode Sent From Server";
    }
}
然后数据包id变为513,我无法理解为什么在PacketEncoderSendCharacterCreationResult中,您通过网络发送三个变量

out.writeInt(2);
out.writeBoolean(exists);
out.writeBoolean(success);
确保无论您在哪里读取数据,您都在读取所有三个变量,看起来您仍然在使用我不推荐的数据包系统,这确实需要更换。您将在本系列后面的第11部分中看到

您未能提供当客户端接收到两个数据包id时处理的代码,但您看到的结果是由于TCP流中存在剩余数据

在不推荐使用的系统中,通过客户机发送的第一件事情是整数32位,客户机将其解释为数据包标识号或操作码。在您当前位置周围的某个视频中,我们将数据包头从字节8位读取的方式更改为Int32位。请确保在客户端上读取数据包idopcode时读取的是整数而不是字节

编辑:我看到你已经这样做了,没有注意到张贴的代码

完成此操作后,在收到2的操作码时,进入正在调用的任何方法,然后确保正确地从PacketsInCharacterCreate读取所有数据。您需要发出两个DataInputStreamReadBoolean调用。注意:DataInputStream实例在应用程序中称为ClientInput


在你发布PacketsInCharacterCreate的代码之前,我再也帮不了你了

我终于明白了!问题出在PacketDecoderLogin方法中,当登录成功时,它正在读取服务器未发送的int,所以我所做的是,将这两行代码置于else条件下 此代码在登录中

字节操作码=ClientInput.ReadByte; Log GetLoginMessage操作码; }

这是因为如果值为false,服务器将发送操作码


一切都很好!也许你应该通知其他人,因为我检查了视频,你像我一样在其他条件之外得到了它

没有看到接收数据的实际代码,甚至无法开始评论可能的错误。但是你的第一步是调试更多的问题;你需要做更多的研究,包括从传输到最终接收的每一步都要检查数据,这样你就可以首先准确地知道数据被误解的地方。我敢打赌你肯定在某个地方遇到了字节排序问题,但这只是一个猜测。看,嘿,彼得,我的英语不是很好,我尽了最大的努力…我将尝试编辑它并添加更多的内容。此外,我想评论一下,彼得·杜尼霍也是正确的,但这不是目前影响应用程序的因素。我会知道的,因为我写了原始教程。但是,您正在使用的DataInputStream版本已弃用,应予以替换。教程系列第11部分中的下载链接我没有提供CharacterCreate,因为InputLoop不运行调用CharacterCreate的案例2,而是运行案例0,该案例0是包含int-opcode=ClientInput.ReadInt的登录名,并且操作码变为2,因此线程有问题,这2应该由InputLoop的int packetID=ClientInput.ReadInt;读取。如果您未通知,我在clientINput.ReadInt之后有Debug.LogpacketID;它是在操作码的Debug.Log之后执行的,它会打印出513号,我不知道它们是如何无序执行的,这甚至是不可能的,甚至没有注意到在你的代码中,但是的,这会把所有的东西都抛出循环。