简体   繁体   English

c#中的文件传输问题

[英]File transfer issue in c#

I am transferring files using c#. 我正在使用c#传输文件。 I have used this code. 我用过这段代码。 The problem is small files like .txt files are transferred correctly but not big files like images, documents, pdf, ppt. 问题是像.txt文件这样的小文件是正确传输的,但不是大文件,如图像,文档,pdf,ppt。 Sometimes code works fine but most of the times it transfers less amount of data. 有时代码工作正常,但大多数情况下它传输的数据量较少。

Server Code: 服务器代码:

Socket clientSock = sock.Accept();

byte[] clientData = new byte[1024 * 50000];
int receivedBytesLen = clientSock.Receive(clientData);
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + "/" + fileName, FileMode.Append));
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
bWrite.Close();
clientSock.Close();

Client Code: 客户代码:

byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
byte[] fileData = File.ReadAllBytes(filePath + fileName);
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
clientSock.Connect(ipEnd);
clientSock.Send(clientData);
clientSock.Close();

Complete code is given in the above link. 完整代码在上面的链接中给出。 I have also seen this post but this is not helpful. 我也看过这篇文章,但这没有用。

Sometimes code works fine but most of the times it transfers less amount of data. 有时代码工作正常,但大多数情况下它传输的数据量较少。

That's the nature of Socket.Receive() , it doesn't always return all data that gets sent to it. 这是Socket.Receive()的本质,它并不总是返回发送给它的所有数据。

You'll have to do a Receive(clientData, 4, 0) first to receive the bytes that indicate the size , then call Receive(clientData) in a loop until you've received size bytes. 您必须首先Receive(clientData, 4, 0)以接收指示size的字节,然后在循环中调用Receive(clientData) ,直到您收到size字节为止。 But beware that the Receive(buffer[], length, offset) overload just as easily as any other overload can return less than the expected amount of bytes. 但请注意, Receive(buffer[], length, offset)重载与任何其他重载一样容易返回, 返回的字节数少于预期的字节数。 So you'll also have to call that in a loop: 所以你还必须在循环中调用它:

Something like this: 像这样的东西:

// First receive the size
int sizeSize = 4; // Size of Int32 in bytes
int sizeOffset = 0;
var sizeBytes = new byte[sizeSize];
while (sizeOffset < sizeSize)
{
    sizeOffset += clientSocket.Receive(sizeBytes, sizeSize - sizeOffset, sizeOffset);
}

var size = BitConverter.ToInt32(sizeBytes, 0);

// Then receive the data
byte[] fileData = new byte[size];
byte[] clientData = new byte[8192];
int totalBytes = 0;

while (totalBytes < size)
{
    // This may return anything between 0 and 8192, even if not all sent data has been received yet. It may be in a buffer somewhere, waiting to be picked up. Check for 0, since that's when the client disconnects.
    int bytesReceived = clientSocket.Receive(clientData);

    // You now have received a chunk of data of bytesReceived length. Append it into the fileData array.
    Buffer.BlockCopy(clientData, 0, fileData, totalBytes, bytesReceived);

    totalBytes += bytesReceived;
}

As CodeCaster's answered that Socket.Receive(), it doesn't always return all data that gets sent to it. 由于CodeCaster回答了Socket.Receive(), it doesn't always return all data that gets sent to it. This is 100% correct and tested but the next step of sending the file size is not working, I found an easy and correct solution. 这是100%正确和测试,但下一步发送文件大小不起作用,我找到了一个简单而正确的解决方案。

Socket.Receive() method takes the byte array in which received data will be copied and returns the number of bytes received. Socket.Receive()方法获取将复制接收数据的字节数组,并返回接收的字节数。 So we can easily loop it till bytes received are 0. 因此我们可以轻松地循环它直到收到的字节为0。

byte[] tempData = new byte[1024 * 5000];

BinaryWriter bWrite = null;
int bytes_received;
int fileNamelength = 0;
bool isFirstPacket = true;

do
{
    bytes_received = clientSock.Receive(tempData);
    if(isFirstPacket)
    {
        isFirstPacket = false;
        int fileNameLen = BitConverter.ToInt32(tempData, 0);
        string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);

        bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Append))
        bWrite.Write(tempData, 4 + fileNameLength, bytes_received - 4 - fileNamelength);
    }
    else
        bWrite.Write(tempData, 0, bytes_received);
}
while (bytes_received != 0);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM