我更像是一个 Java 开发人员而不是 C# 开发人员,但我使用两种语言;不幸的是,我远不及大多数语言的人的水平,但这就是为什么我不断提出问题和阅读以扩展我的知识。
目前,我一直在用Java开发服务器/客户端,它运行良好,我已经用Java为我一直在Unity3D中开发的游戏编写了一个测试客户端。老实说,如果社区在那里轻松获得关卡设计师等,我会在整个游戏中使用 Java。
在此代码中,我在java中使用了BufferedInputStream,设置如下所示:
DataInputStream dataIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
在整个代码中,我执行以下逻辑来检查以确保指定数据包的所有数据都已到达:
if(dataIn.available() < 4) {
continue;
}
dataIn.mark(4);
int length = dataIn.readInt();
System.out.println("Packet length is" + length);
if(dataIn.available() < length) {
System.out.println("Only read " + dataIn.available() + "/ " + length + " bytes.");
dataIn.reset();
continue;
}
我一直在努力在 C# 中找到与此等效的。 -- 我注意到的其他问题是,Java 的 DataOutputStream 发送的字节和 C# 的 BinaryReader 读取的字节并不总是相同的,但这是另一个问题。
像这样的东西会读取内存流中的所有预期数据。通过使用内存流作为流,或者通过使用memoryStream.ToArray()获取其中的字节,可以对接收到的数据进行进一步处理。
using (var ns = new NetworkStream(socket))
{
int dataLength = 0;
// reading the datalength
for (int i = 0; i < 4; i++)
{
while (!ns.DataAvailable)
{
System.Threading.Thread.Sleep(20);
}
dataLength = (dataLength << 8) + ns.ReadByte();
}
// reading the data
byte[] buffer = new byte[1024];
int bytesRead;
using (var memoryStream = new MemoryStream())
{
while (memoryStream.Length < dataLength)
{
while (!ns.DataAvailable)
{
System.Threading.Thread.Sleep(20);
}
bytesRead = ns.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, bytesRead);
}
}
}
编辑:简约的方法
小心插座。使用此方法时的接收缓冲区大小!如果它小于数据大小,您将处于长时间睡眠状态。
Socket socket = listener.AcceptSocket();
while (socket.Available < 4)
{
System.Threading.Thread.Sleep(20);
}
byte[] lengthBuffer = new byte[4];
socket.Receive(lengthBuffer);
if (BitConverter.IsLittleEndian) Array.Reverse(lengthBuffer);
int dataLength = BitConverter.ToInt32(lengthBuffer, 0);
while (socket.Available < dataLength)
{
System.Threading.Thread.Sleep(20);
}
byte[] dataBuffer = new byte[dataLength];
socket.Receive(dataBuffer);