通过网络编写数据

时间:2015-05-21 03:14:27

标签: java c#

我正在使用C#进行基本的网络实现,这将允许我将数据发送到我的Java服务器。服务器已经过一段时间的测试,并完成了Java客户端需要做的所有事情,现在我正在努力学习C#客户端开发。

我遇到的问题是服务器正在读取我通过C#客户端发送的每个数据包操作码为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);
    }
}

这是Packet类:

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个long(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 个答案:

答案 0 :(得分:1)

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

因此,您可以删除整个ObjectToByteArray方法,在创建BinaryWriter时创建MemoryStream对象,并将数据Write()添加到其中。最后,您在MemoryStream中拥有了所需的一切,它将比创建许多临时对象的当前效率更高效。

答案 1 :(得分:0)

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

long值相同。

为什么不查看b方法中Write包含的内容?这将是比您预期更多的数据。

相关问题