2015-05-21 92 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中擁有了你所需要的一切,並且比創建許多臨時對象的當前效率更高效。