我正在使用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();
如果有人能帮助我,我会非常感激。
答案 0 :(得分:1)
不要使用BinaryFormatter
来编写原始数据。 BinaryWriter
是要走的路。它允许您在没有任何对象信息的情况下写入数据,因此一个字节将是一个字节,一个int将是一个int,一个字符串将是一个只有长度信息编码的字符串。
因此,您可以删除整个ObjectToByteArray
方法,在创建BinaryWriter
时创建MemoryStream
对象,并将数据Write()
添加到其中。最后,您在MemoryStream
中拥有了所需的一切,它将比创建许多临时对象的当前效率更高效。
答案 1 :(得分:0)
当您在代码中调用packet.Write((byte)3);
时,实际上并没有写入单个字节。相反,它写了一个序列化对象(恰好是一个字节) - 实际上,这将是字节本身,加上围绕它的几个字节基本上说&#34;这是一个字节&#34;。
long
值相同。
为什么不查看b
方法中Write
包含的内容?这将是比您预期更多的数据。