为什么BinaryReader在Thread内部,从netty读取错误的包数据?

时间:2014-11-17 22:27:22

标签: java c# sockets unity3d netty

我正在将netty中的数据发送到统一3d游戏引擎中的c#应用程序,其中它读取数据包ID并根据数据包ID(在线程内)执行不同的方法,BinaryReader读取的数据包ID错误且我无法理解为什么

这里是类custombuffer,datainputstream,dataoutputstream:https://docs.google.com/document/d/1LmW8fzGFFnkgqV_kS-TnBi7XvVYTC4Q4kHWJT60UF00/edit?usp=sharing

你没有仔细阅读它们我发布它们以便你知道它们是什么

这是登录方法

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

在登录后,其处理的perfectrly服务器发送带有数据包ID 2的字符创建结果,当它到达客户端时,它首先运行packetsIn.Login()(这是0的packetid)和writeInt(2)来自SendCharacterCreationResult 从下面的方法中获取,其中byte opcode = ClientInput.ReadByte(); 等于(2)我尝试了这样的int opcode = clientInput.ReadInt();它给出了相同的结果。如果我困惑你告诉我在文本中添加完整的文件

这是inputloop(在线程中运行)中的case 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,我无法理解为什么

2 个答案:

答案 0 :(得分:0)

PacketEncoder#SendCharacterCreationResult中,您通过网络发送三个变量

out.writeInt(2);
out.writeBoolean(exists);
out.writeBoolean(success);

确保无论您在何处阅读所有三个变量的数据,您似乎仍在使用我已弃用的​​数据包系统,而这个数据库系统确实需要更换(您将在本系列的后续版本中找到它) ,来到第11部分)

您无法提供客户端收到数据包ID为2时处理的代码,但您看到的结果是由于TCP流中存在剩余数据。

在不推荐使用的系统中,您通过客户端发送的第一件事是整数(32位),客户端将其解释为数据包标识号(或操作码)。在你周围某个地方的视频中,我们改变了将数据包标头从字节(8位)读取到Int(32位)的方式,确保在读取数据包id(操作码)时客户端你正在读取整数而不是字节。

EDIT: I see that you already did this, didn't notice the posted code

完成上述操作后,请在收到Opcode of 2时调用您正在调用的任何方法,然后确保从PacketsIn#CharacterCreate正确读取所有数据。发出两个DataInputStream#ReadBoolean()来电。 (注意: DataInputStream实例在您的应用程序中称为 ClientInput )。

在您发布PacketsIn#CharacterCreate()代码之前,我无法继续提供帮助。

答案 1 :(得分:0)

终于我明白了!问题出在PacketDecoder#Login()方法中,当登录成功时它正在读取服务器发送的一个int,所以我做了什么,我把这两行代码放在&#34;别的&#34;条件 此代码位于Login()

byte opcode = ClientInput.ReadByte (); Debug.Log( GetLoginMessage (opcode) ); }

这是有效的,因为如果值为false,服务器会发送opcode

一切正常!也许你应该通知别人,因为我检查了视频,你在其他情况之外就像我一样得到它