2015-05-21 91 views
1

我正在研究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); 
    } 
} 

这里的包类:

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

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

+0

ObjectToByteArray是做什么的?你似乎正在调用每个字节/长。 – immibis

+0

对不起,将它添加到问题 – Hobbyist

+0

@immibis - Ahaha,将其删除。 – Hobbyist

回答

0

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

相同的为long值。

为什么不看b包含在Write方法中?它会比你预期的数据更多。

+0

我该如何解决这个问题?我对C#不是很满意,坦率地说不喜欢这种语言,不幸的是这只是我必须克服的一些问题。 我有一个通过引用Java的DataOutputStream创建的Stream,但它确实很复杂。尝试使用标准的C#代码轻松找到一种方法。 – Hobbyist

+0

@ Christian.tucker对于字节,直接写入缓冲区。长期以来,我不知道C#是否有相当于DataOutputStream。 – immibis

1

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

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