Search code examples
socketsc#-4.0file-transferfilewriter

Half file transferring in c# via socket?


I am developing the file transfer application via middle level greedy routing in which file sends to greedy and greedy sends file again to router but he problem is some time client receives complete file and some time it receive some part of file

Here my code goes Server Side

IPAddress[] ipAddress = Dns.GetHostAddresses("127.0.0.1");
            IPEndPoint ipEnd = new IPEndPoint(ipAddress[0], 5655);
            Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);


            string filePath = "";


            fileDes = fileDes.Replace("\\", "/");
            while (fileDes.IndexOf("/") > -1)
            {
                filePath += fileDes.Substring(0, fileDes.IndexOf("/") + 1);
                fileDes = fileDes.Substring(fileDes.IndexOf("/") + 1);
            }


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

            lblError.Text = "";
            lblError.Text = "Buffering ...";
            byte[] fileData = File.ReadAllBytes(filePath + fileDes);
            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);

            lblError.Text = "";
            lblError.Text = "Connection to server ...";
            clientSock.Connect(ipEnd);

            lblError.Text = "";
            lblError.Text = "File sending...";
         //   System.Threading.Thread.Sleep(1000);
            clientSock.Send(clientData);
            label3.Text = clientData.Length.ToString();

            lblError.Text = "";
            lblError.Text = "Disconnecting...";
            clientSock.Close();

            lblError.Text = "";
            lblError.Text = "File transferred.";

In client

class DestCode
{
    IPEndPoint ipEnd;
    Socket sock;
    public DestCode()
    {
       ipEnd = new IPEndPoint(IPAddress.Any, 5656);
       sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
       sock.Bind(ipEnd);
    }
    public static string receivedPath;
    public static string curMsg = "Stopped";
    public static int res;
    public  void StartServer()
    {
        try
        {
            curMsg = "Starting...";
            sock.Listen(100);

            curMsg = "Running and waiting to receive file.";
            Socket clientSock = sock.Accept();

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

            int receivedBytesLen = clientSock.Receive(clientData);

            curMsg = "Receiving data...";

            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);
            res = receivedBytesLen;
            if (receivedPath == "")
            {
                MessageBox.Show("No Path was selected to Save the File");
            }
            curMsg = "Saving file...";

            bWrite.Close();
            clientSock.Close();
            curMsg = "File Received ...";

            StartServer();

        }
        catch (Exception ex)
        {
            curMsg = "File Receving error.";
        }
    }
}

In Greedy

class ReceiverCode
{
    IPEndPoint ipEnd;
    Socket sock;
    public ReceiverCode()
    {
        ipEnd = new IPEndPoint(IPAddress.Any, 5655);
        sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
        sock.Bind(ipEnd);
    }
    public static string receivedPath;
    public static string curMsg = "Stopped";
    public static string Rout = "";
    public static int rlength = 0;
    public static string MsgStatus = "";
    public static byte[] send;
    public void StartServer()
    {
        try
        {
            curMsg = "Starting...";
            sock.Listen(100);

            curMsg = "Running and waiting to receive file.";
            Socket clientSock = sock.Accept();

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

            int receivedBytesLen = clientSock.Receive(clientData);
           System.Threading.Thread.Sleep(5000);
            rlength = receivedBytesLen;
            curMsg = "Receiving data...";

            int receive = clientSock.Receive(clientData);


            send = new byte[receivedBytesLen];
            Array.Copy(clientData, send, receivedBytesLen);
            Rout = "Start";
            clientSock.Close();
            curMsg = "Reeived & Saved file; Server Stopped.";
            StartServer();

        }
        catch (Exception ex)
        {
            curMsg = "File Receving error.";
        }
    }


}

Please somebody help me


Solution

  • The problem is that Socket.Receive does not guarantee that you'll receive all the bytes you asked for. So you write:

    int receivedBytesLen = clientSock.Receive(clientData);
    

    The documentation says:

    If you are using a connection-oriented Socket, the Receive method will read as much data as is available, up to the size of the buffer.

    The call to Receive is getting all of the bytes that are currently available. It could be that the sender hasn't yet sent all of the bytes, or that your network stack hasn't received them and made them available.

    To reliably send and receive data, the receiver has to know one of two things: either how many bytes it's expecting, or that there is some sentinel value that says, "that's all, folks." You can't count on a single Receive call to get everything.

    When transferring files, the sender typically includes the size of the file as the first four bytes of the data being sent. Your code then reads the first four bytes (making sure that you get all four bytes) to determine the size, and then spins a loop, reading data from the socket until all of the expected bytes are received.

    Something like:

    const int MaximumSize = 1000000;
    // read the first four bytes
    var sizeBytes = ReadBytesFromSocket(socket, 4);
    int size = BitConverter.ToInt32(sizeBytes);
    
    var dataBuffer = ReadBytesFromSocket(socket, size);
    // you now have your data
    
    byte[] ReadBytesFromSocket(Socket socket, int size)
    {
        var buff = new byte[size];
        int totalBytesRead = 0;
    
        while (totalBytesRead < size)
        {
            int bytesRead = socket.Receive(buff, totalBytesRead, size-totalBytesRead, SocketFlags.None);
            if (bytesRead == 0)
            {
                // nothing received. The socket has been closed.
                // maybe an error.
                break;
            }
            totalBytesRead += bytesRead
        }
        return buff;
    }
    

    See my blog post on reading streams (and the linked parts 1 and 2) for more information. The blog posts talk about streams, but the concepts are the same with sockets.