none
File corruption over .net sockets RRS feed

  • Question

  • so I made a small P2P Program using TCP, and when I send large files, receiver end gets corrupted data, don't know what I can do to fix, I've been coding since 2015 but haven't really got back fully into it, still know how to code, just a little rusty right now.

    here's my code

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;

    namespace FileBucket.Service {

        class SendFileService {

            public FileProgressEventHandler FileSendProgress;
            public FileSharedCompleteEventHandler FileSendComplete;
            public ConnectEventHandler Connect;

            public static int bufferSize = 4096;
            TcpClient client;
            private Task task = null;

            public String FilePath { get; set; }

            public long FileSize { get; private set; }

            public SendFileService(String filePath) {
                FilePath = filePath;
                FileSize = new FileInfo(filePath).Length;

                //Linstener for validation
                Task.Run(() => {
                    TcpListener listener = new TcpListener(4975);
                    listener.Start();
                });
            }

            public void StartListening() {
                Task.Run(() => {
                    if (Connect != null) Connect(Connection.Connecting);
                    client = FileShareService.GetNewClient();
                    if (Connect != null) Connect(Connection.Successful);
                });
            }

            public void SendFileAsync() {
                task = Task.Run(() => {
                    sendFile();
                });
            }

            private void sendFile() {
                using (Stream stream = client.GetStream()) {
                    //Send file size
                    FileInfo fileInfo = new FileInfo(FilePath);
                    int fileSize = (int) fileInfo.Length;
                    byte[] fileSizeBytes = BitConverter.GetBytes(fileSize);
                    stream.Write(fileSizeBytes, 0, 4);

                    //Send file name
                    byte[] fileNamebytes = Encoding.ASCII.GetBytes(fileInfo.Name);
                    fileSizeBytes = BitConverter.GetBytes(fileNamebytes.Length);
                    stream.Write(fileSizeBytes, 0, 4);
                    stream.Write(fileNamebytes, 0, fileNamebytes.Length);

                    using (FileStream fileStream = new FileStream(FilePath, FileMode.Open)) {
                        //int count = (int)(fileSize / bufferSize);
                        //int rest = (int)(fileSize % bufferSize);

                        //byte[] fileBytes = new byte[bufferSize];
                        //if (FileSendProgress == null) {
                        //    for (int i = 0; i < count; i++) {
                        //        fileStream.Read(fileBytes, 0, bufferSize);
                        //        System.Threading.Thread.Sleep(10);
                        //        stream.Write(fileBytes, 0, bufferSize);
                        //    }
                        //} else {
                        //    for (int i = 0; i < count;) {
                        //        fileStream.Read(fileBytes, 0, bufferSize);
                        //        System.Threading.Thread.Sleep(10);
                        //        stream.Write(fileBytes, 0, bufferSize);
                        //        i++;
                        //        FileSendProgress(i / (double)count);
                        //    }
                        //}

                        ////Rest Bytes
                        //fileBytes = new byte[rest];
                        //fileStream.Read(fileBytes, 0, rest);
                        //stream.Write(fileBytes, 0, rest);


                        #region
                        byte[] fileBytes = new byte[fileSize];
                        fileStream.Read(fileBytes, 0, fileSize);
                        stream.Write(fileBytes, 0, fileSize);

                        if (FileSendProgress != null) FileSendProgress(1);
                        #endregion
                    }
                }

                //File send competed
                if (FileSendComplete != null) FileSendComplete();
                client.Close();
            }

            public void CancelSending() {
                client.Close();
            }
        }
    }

    -------

    these are split into "services"

    -----

                                

    using

    System

    ;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;

    namespace FileBucket.Service {
        class ReceiveFileService {

            public FileProgressEventHandler FileReceiveProgress;
            public FileSharedCompleteEventHandler FileReceivedComplete;
            public ConnectEventHandler Connect;
            TcpClient client;

            public static int bufferSize = 4096;
            public String FilePath { get; set; }

            public long FileSize { get; private set; }

            public String HostName { get; set; }

            public bool IsValidHostName() {
                try {
                    TcpClient client = new TcpClient(HostName, 4975);
                    client.Close();
                } catch (Exception e) {
                    return false;
                }
                return true;
            }

            public void ReceiveFileAsync() {
                Task.Run(() => {
                    ReceiveFile();
                });
            }

            public void GetFileInfo() {
                client = new TcpClient(HostName, config.Configuration.PORT);
                Stream stream = client.GetStream();
                    //Receive file size
                    byte[] fileSizeBytes = new byte[4];
                    stream.Read(fileSizeBytes, 0, 4);
                    int fileSize = BitConverter.ToInt32(fileSizeBytes, 0);
                    FileSize = fileSize;

                    //Receive File name
                    stream.Read(fileSizeBytes, 0, 4);
                    int fileNameLen = BitConverter.ToInt32(fileSizeBytes, 0);
                    byte[] fileNamebytes = new byte[fileNameLen];
                    stream.Read(fileNamebytes, 0, fileNameLen);
                    string fileName = Encoding.ASCII.GetString(fileNamebytes);
                    FilePath = fileName;

            }

            private void ReceiveFile() {
                using (Stream stream = client.GetStream()) {
                    if (Connect != null) Connect(Connection.Successful);

                    using (FileStream fileStream = new FileStream(FilePath, FileMode.Create)) {
                        //int count = (int)(fileSize / bufferSize);
                        //int rest = (int)(fileSize % bufferSize);

                        //byte[] fileBytes = new byte[bufferSize];
                        ////TODO hard code replace this
                        //FilePath = "D:\\downloaded_image.jpg";

                        //if (FileReceiveProgress == null) {
                        //    for (int i = 0; i < count; i++) {
                        //        stream.Read(fileBytes, 0, bufferSize);
                        //        System.Threading.Thread.Sleep(10);
                        //        fileStream.Write(fileBytes, 0, bufferSize);
                        //    }
                        //} else {
                        //    for (int i = 0; i < count;) {
                        //        stream.Read(fileBytes, 0, bufferSize);
                        //        System.Threading.Thread.Sleep(10);
                        //        fileStream.Write(fileBytes, 0, bufferSize);
                        //        i++;
                        //        FileReceiveProgress(i / (double)count);
                        //    }
                        //}

                        ////Rest Bytes
                        //fileBytes = new byte[rest];
                        //stream.Read(fileBytes, 0, rest);
                        //fileStream.Write(fileBytes, 0, rest);
                        //if (FileReceiveProgress != null) FileReceiveProgress(1);

                        #region
                        int fileSize = (int)FileSize;
                        byte[] fileBytes = new byte[fileSize];
                        stream.Read(fileBytes, 0, fileSize);
                        fileStream.Write(fileBytes, 0, fileSize);
                        if (FileReceiveProgress != null) FileReceiveProgress(1);
                        #endregion
                    }
                }

                //File received complete
                if (FileReceivedComplete != null) FileReceivedComplete();
            }
        }
    }

    ------

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;

    namespace FileBucket.Service {

        public delegate void FileProgressEventHandler(double progress);
        public delegate void FileSharedCompleteEventHandler();
        public delegate void ConnectEventHandler(Connection connection);

        public enum Connection { Connecting, Successful}

        class FileShareService {
            private static TcpListener listner;

            public static String HostName {
                get {
                    return Dns.GetHostName();
                }
            }

            public static int Port { get; private set; }

            public static void StartListener() {
                int port = config.Configuration.PORT;
                //Generate port number
                while (true) {
                    try {
                        listner = new TcpListener(port);
                        listner.Start();

                        break;
                    } catch (ArgumentOutOfRangeException outOfRange) {

                    } catch (SocketException socketException) {
                        port++;
                    }
                }
                Port = port;
            }

            public static TcpClient GetNewClient() {
                return listner.AcceptTcpClient();
            }

            public static void StopListener() {
                listner.Stop();
            }
        }
    }

    Thursday, January 23, 2020 4:08 AM

All replies

  • Corrupted in what way?  Is the file size correct?  TCP is a "guaranteed" protocol; whatever packets go out will be retried until they succeed, barring a dropped connection.

    Having said that, most transfer programs do large files in smaller chunks, if for no other reason than they can display things like progress bars.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Thursday, January 23, 2020 7:50 AM
  • so I transferred an image to see what it would do, and on the receivers end the picture sends but only 20% of it is a picture the rest is a grey box, It has the correct file size, just a weird picture/grey out picture in 1
    • Edited by Specter FXX-K Thursday, January 23, 2020 11:18 AM forgot to add some info
    Thursday, January 23, 2020 11:17 AM
  • Now you get to debug it.  Have you looked at a binary dump of the two files to see how they differ?  Is it just a few bytes?  Are there whole chunks missing or replaced with zeros?  Were packets written in the wrong order?

    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Friday, January 24, 2020 8:12 AM