简体   繁体   中英

C# How to send a 1GB file using TCP client

public void SendFile(string remoteHostIP, int remoteHostPort, string longFileName, string shortFileName)
{
    byte[] fileNameByte = Encoding.ASCII.GetBytes(shortFileName);
    byte[] fileData = File.ReadAllBytes(longFileName);
    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);
    TcpClient clientSocket = new TcpClient(remoteHostIP, remoteHostPort);
    NetworkStream networkStream = clientSocket.GetStream();
    networkStream.Write(clientData, 0, clientData.GetLength(0));
    networkStream.Close();     
}

It is possible to use this function to send a 1GB file because the maximum file size i had been try to send now is only up to 400MB. More than that is will cause an error of 'System.OutOfMemoryException'. When i use another method to split the file into few parts but the server side can't receive the parts continuously and can only receive one of the part.

    private void splitBigFile(string FileInputPath, byte[] inputArray)
    {
        int port = 1113;

        double partSize = 104852000;
        int partSize2 = 104852000;

        string FolderOutputPath = "C:\\Users\\xx\\Desktop\\testing split";
        string currPartPath;
        string shortNameSplit;

        FileStream fileStream = new FileStream(FileInputPath, FileMode.Open);
        FileInfo fiSource = new FileInfo(txtFile.Text);
        double sourceLength = fiSource.Length;

        partNum = (int)Math.Ceiling((double)(sourceLength / partSize));

        for (int i = 0; i < partNum; i++)
        {
            if (i == (partNum - 1))
            {
                partSize2 = (int)fiSource.Length - (i * 104852000);
            }

            currPartPath = FolderOutputPath + "\\" + fiSource.Name + "." + String.Format(@"{0:D4}", i) + ".part";
            shortNameSplit = fiSource.Name + "." + String.Format(@"{0:D4}", i) + ".part";

            byte[] fileNameByte = Encoding.ASCII.GetBytes(shortNameSplit);

            byte[] readStream = new byte[partSize2];

            byte[] concateFile = new byte[5 + fileNameByte.Length];

            int ipSend = ((partNum - 1 - i) << 1);
            ipSend |= 0; // for differentiate ip or file
            byte[] byteSend = new byte[1];
            byteSend[0] = (byte)ipSend;

            fileStream.Read(readStream, 0, partSize2);
            byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);

            byteSend.CopyTo(concateFile, 0);
            fileNameLen.CopyTo(concateFile, 1);
            fileNameByte.CopyTo(concateFile, 5);
            concateFile.CopyTo(inputArray, 0);
            readStream.CopyTo(inputArray, concateFile.Length);
            string ipAddress = "192.168.43.67";
            int sendport = 1113;
            //Task.Factory.StartNew(() => SendBigFileSize(ipAddress, sendport, inputArray[i]));
            Array.Clear(readStream, 0, readStream.Length);
            Array.Clear(fileNameLen, 0, fileNameLen.Length);
            Array.Clear(fileNameByte, 0, fileNameByte.Length);
            Array.Clear(byteSend, 0, byteSend.Length);
            Array.Clear(byteSend, 0, byteSend.Length);
        }
        fileStream.Close();
    }

Of course, just not all at once. Send chunks at a time.

Besides, the maximum TCP packet size is 64k, and the MTU is 1500 bytes. Your huge buffer is getting split up too, but you're using up a lot of memory doing it. Instead read 32MB (safe HDD I/O buffer size) at a time from your file and send it, then read the next bit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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