有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java通过网络写入数据

我正在用C#开发一个基本的网络实现,它将允许我向Java服务器发送数据。该服务器已经测试了相当长的一段时间,它可以用Java客户机完成所有需要做的事情,现在我正在尝试学习C#客户机开发

我遇到的问题是,服务器将我通过C#client发送的每个数据包操作码都读取为0,因此不执行任何逻辑。数据在服务器上以字节的形式读取。这是我的设置

public class NetworkClient {

    public static NetworkClient Create() {
        return new NetworkClient ();
    }

    private Queue<Task> tasks = new Queue<Task>();

    private String HostAddress = "localhost";

    private int Port = 5055;

    private TcpClient _tcpClient;

    private NetworkStream _networkStream;

    private NetworkClient() {

    }

    public void Update() {
        while (tasks.Count > 0) 
            tasks.Dequeue () ();
    }

    public void Submit(Task task) {
        tasks.Enqueue (task);
    }

    public NetworkClient SetPort(int port) {
        Port = port;
        return this;
    }

    public NetworkClient SetHostAddress(String hostAddress) {
        HostAddress = hostAddress;
        return this;
    }

    public NetworkClient Connect() {
        _tcpClient = new TcpClient (HostAddress, Port);
        _networkStream = _tcpClient.GetStream ();
        return this;
    }

    public bool IsConnected() {
        return _tcpClient.Connected;
    }

    public NetworkClient Disconnect() {
        _tcpClient.Close ();
        return this;
    }

    public void Write(Packet packet) {
        _networkStream.Write (packet.buffer.ToArray (), 0, (int)packet.buffer.Length);
    }
}

以下是数据包类:

public class Packet {
    public int Opcode;
    public MemoryStream buffer;

    public static Packet Create(int opcode) {
        return new Packet (opcode, 128);
    }

    public static Packet Create(int opcode, int capacity) {
        return new Packet (opcode, capacity);
    }

    private Packet(int opcode, int capacity) {
        Opcode = opcode;
        buffer = new MemoryStream(capacity);
    }

    public Packet Write(Object o) {
        byte[] b = ObjectToByteArray (o);
        buffer.Write (b, 0, b.Length);
        return this;
    }

    private byte[] ObjectToByteArray(Object obj)
    {
        if(obj == null)
            return null;
        BinaryFormatter bf = new BinaryFormatter();
        using(MemoryStream ms = new MemoryStream())
        {
            bf.Serialize(ms, obj);
            return ms.ToArray();
        }
    }
}

调用并执行此代码,以向服务器发送包含以下代码的数据包:

public static void Main() {
        NetworkClient client = NetworkClient.Create ().Connect ();
        Packet packet = Packet.Create (1);
        packet.Write ((byte)3);
        packet.Write (100L);
        packet.Write (100L);
        packet.Write (100L);
        packet.Write (1840979156127491L);
        client.Write (packet);
        Console.ReadKey ();
    }

这应该写入一个字节(操作码,值为3),然后通过网络写入4个长(Int64)。总大小为33字节

然而,服务器正在读取282字节

执行下面的代码(Java),基本上做同样的事情,读取正确数量的数据(33字节)并正确处理

ByteBuffer buffer = ByteBuffer.allocate(65);
                buffer.put((byte) 3); //opcode
                buffer.putLong(100L);
                buffer.putLong(100L);
                buffer.putLong(100L);
                buffer.putLong(1840979156127491L);
                buffer.flip();
                channel.write(buffer);
                buffer.compact();

如果有人能帮助我,我将非常感激


共 (2) 个答案

  1. # 1 楼答案

    当您在代码中调用packet.Write((byte)3);时,实际上并没有写入一个字节。相反,它编写一个序列化对象(恰好是一个字节)——实际上,这将是字节本身,加上它周围的几个字节,基本上说“这是一个字节”

    对于long值也是如此

    为什么不看看b方法中包含了什么?数据量将超过你的预期

  2. # 2 楼答案

    不要使用BinaryFormatter来写入原始数据^{}是一条路要走。它允许您在没有任何对象信息的情况下写入数据,因此字节将是字节,整数将是整数,字符串将是一个只编码长度信息的字符串

    因此,您可以删除整个ObjectToByteArray方法,在创建MemoryStream时创建一个BinaryWriter对象,然后只Write()将数据放入其中。最终,你在MemoryStream中拥有了你所需要的一切,而且它将比当前创建许多临时对象的方法更加高效