因此我遇到了服务器/客户端应用程序的问题,我正在编写将文件从服务器发送到客户端。
在服务器端发送文件时,有一个循环可以发送最多16kb的缓冲区,直到发送完整文件为止。
当客户端收到文件时,它会一次接收最多16kb缓冲区中的文件,直到获得完整文件。
这是奇怪的部分。我认为这可能是我设置错误导致我的问题的一个属性。如果我在客户端接收5ms的结束循环时睡眠,它可以正常工作(在我的本地电脑上)。每个文件都会没有问题。如果没有睡眠定时器,有时文件传输将起作用,有时数据包在传输过程中会被破坏。
我有一个朋友尝试运行客户端,看看它是否适用于5ms睡眠的人。问题是对于他们我们必须实际提高睡眠定时器以避免损坏数据包。我们最终将睡眠定时器提升到100毫秒,发现每个文件都可以通过这种方式成功传输,但问题是速度太慢了。
有谁知道造成这个幽灵的原因是什么?
如果有人对send方法和接收方法感兴趣,那么它们就是
public bool SendFile(string SendFilePath, string ActualFilePath)
{
//First send packet to start sending file
try
{
if (!SendInt32((Int32)PacketType.StartUpdate))
return false;
if (!SendString(SendFilePath))
return false;
if (!GetInt32(out packettype))
return false;
if (packettype != (Int32)PacketType.ConfirmationPacket)
{
Console.WriteLine("0x0 Expected Confirmation Packet, but instead received: " + packettype);
return false;
}
}
catch
{
clientSocket.Close();
Console.WriteLine("Error upon attempting to send 'Start File Update' packet.");
return false;
}
//Next send the file
BinaryReader FileToSend = new BinaryReader(File.OpenRead(ActualFilePath));
int FileSize = (int)FileToSend.BaseStream.Length;
int FileOffset = 0;
int RemainingSize = (FileSize - FileOffset);
byte[] filebuffer = new byte[MaxPacketSize];
while (RemainingSize > 0)
{
if (RemainingSize >= MaxPacketSize)
{
FileToSend.Read(filebuffer, 0, MaxPacketSize);
if (!SendInt32((Int32)PacketType.ByteBuffer))
return false;
if (!SendByteArray(filebuffer, MaxPacketSize))
return false;
FileOffset += MaxPacketSize;
RemainingSize = (FileSize-FileOffset);
}
else
{
FileToSend.Read(filebuffer, 0, RemainingSize);
if (!SendInt32((Int32)PacketType.ByteBuffer))
return false;
if (!SendByteArray(filebuffer, RemainingSize))
return false;
FileOffset += RemainingSize;
RemainingSize = (FileSize - FileOffset);
}
//Get confirmation packet before sending another packet
if (!GetInt32(out packettype))
{
return false;
}
if (packettype != (Int32)PacketType.ConfirmationPacket)
{
Console.WriteLine("0x2 Expected Confirmation Packet - received: " + packettype);
}
}
FileToSend.Close();
//Next send packet to stop updating this file
try
{
if (!SendInt32((Int32)PacketType.StopUpdate))
return false;
if (!GetInt32(out packettype))
return false;
if (packettype != (Int32)PacketType.ConfirmationPacket)
{
Console.WriteLine("0x1 Expected Confirmation Packet, but instead received: " + packettype);
return false;
}
}
catch
{
clientSocket.Close();
Console.WriteLine("Error upon attempting to send 'Stop File Update' packet.");
return false;
}
Console.WriteLine("File Sent:" + SendFilePath);
return true;
}
客户端在收到StartUpdate数据包后调用ReceiveFile。
public bool ReceiveFile(string rootdir)
{
//First get the FilePath
try
{
if (!GetString(out FilePath)) //If failure to receive a string packet
return false; //crash
Console.WriteLine("Root Dir: "+rootdir+" File Path:" + FilePath);
if (!SendInt32((Int32)PacketType.ConfirmationPacket)) //If failure to send an int packet
return false; //crash
}
catch
{
clientSocket.Close();
Console.WriteLine("Error upon attempting to send 'Start File Update' packet.");
return false; //crash
}
//Next receive the file
BinaryWriter ReceivedFile = new BinaryWriter(File.OpenWrite(rootdir + "\\" +FilePath));
int FileOffset = 0;
byte[] filebuffer;
while (true)
{
Thread.Sleep(100);
if (!GetInt32(out packettype))
return false;
if (packettype != (Int32)PacketType.ByteBuffer && packettype != (Int32)PacketType.StopUpdate)
{
Console.WriteLine("Expected byte buffer or stop update packet. Received: " + packettype);
return false;
}
if (packettype == (Int32)PacketType.StopUpdate)
{
if (!SendInt32((int)PacketType.ConfirmationPacket))
return false;
break;
}
if (packettype == (Int32)PacketType.ByteBuffer)
{
int arraysize;
if (!GetByteArray(out filebuffer, out arraysize))
return false;
ReceivedFile.Write(filebuffer, 0, arraysize);
Console.WriteLine("Success");
FileOffset += arraysize;
if (!SendInt32((int)PacketType.ConfirmationPacket))
return false;
}
}
ReceivedFile.Close();
Console.WriteLine("File Received: " + FilePath);
Console.WriteLine("File Size: " + ((FileOffset / 1024) + 1).ToString() + " KB");
return true;
}
编辑:此外,MaxPacketSize = 16384
答案 0 :(得分:1)
在GetByteArray中,确保获取一个数据包的所有字节。 NetworkStream.Read函数返回读取的字节数,因此请确保它等于您期望的字节数。如果没有,请再次调用,直到您有足够的时间。只需确保更新您的偏移量和剩余字节数。例如,如果您已经收到10个字节,则应该从索引10开始接收,并且只接收buffersize-10个字节(因此您不会溢出)。