收到数据包太快时C#Server问题

时间:2015-11-01 22:43:53

标签: c# ftp server

因此我遇到了服务器/客户端应用程序的问题,我正在编写将文件从服务器发送到客户端。

在服务器端发送文件时,有一个循环可以发送最多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

1 个答案:

答案 0 :(得分:1)

在GetByteArray中,确保获取一个数据包的所有字节。 NetworkStream.Read函数返回读取的字节数,因此请确保它等于您期望的字节数。如果没有,请再次调用,直到您有足够的时间。只需确保更新您的偏移量和剩余字节数。例如,如果您已经收到10个字节,则应该从索引10开始接收,并且只接收buffersize-10个字节(因此您不会溢出)。