Click here to Skip to main content
15,892,746 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
Hi everybody,

first of all I'm sorry about my poor english, as I am from Germany. I please you to excuse that.

My Problem is, I'm trying to send a file via a Socket from one Computer to another. The Sockets aren't connected to each other, but to a Proxy, which handles the Communication. All in all the Communication is working fine and the File is transferred. The problem is the File, which gets newly created by the receiver. It has exactly the same size as the one which was sent, but the content is wrong. For example, I made a testfile, which contains lines like:

1 Test Test Test ...
2 Test Test Test ...
...


All in all the testfile has got 100 lines, each line containing the line number and 30 times the word "Test". The received File partially contains the right content, and partially contains strange things like:

Ýó’]$(ÇuêñâÊ%×%à–áxFøâQó’]$(ÇuêñâÊ%×%à–á


And the corresponding characters within my testfile are missing...

I had a look at was is being sent with Wireshark and figured out, that the Content of the testfile is being sent in the right way. There are no strange Bytes or things like that. Same thing with the packets being received. Then I had a look at my source and tried to debug it. While doing that, I figured out, very very slow receiving of the file fixes the problem, but that isn't suitable for me. Right now I am thinking, that writing the file to my hdd is the problem, so I really tried a hole bunch of different techniques for writing the file to the hdd of the receiver, but I just can't find my mistake.

Just one thing in advance, the application I'm currently developing is a kind of ICQ-Client, so don't be confused by the senderUIN stuff. Ok, here is my sourcecode for receiving the file and writing it to the hdd:

private bool recvFile(Socket tmpSocket, int TotalSize, string filename, string senderUIN, object signal)
        {
            Socket p2pSocket = tmpSocket;
            int totalSize = TotalSize;
            int totalReceived = 0;
            int received = 0;
            byte[] buffer = new byte[1000];
            BinaryWriter writer;

/* Create Directory if it isn't existing */
            if (!System.IO.Directory.Exists(@"./Received Files"))
                System.IO.Directory.CreateDirectory(@"./Received Files");
            /* userspecific directory */
            string user_dir = "./Received Files/" + uin;
            if (!System.IO.Directory.Exists(@user_dir))<
                System.IO.Directory.CreateDirectory(@user_dir);
            writer = new BinaryWriter(File.Open(user_dir + "/" + filename, FileMode.Create));
            while (totalReceived < totalSize)
            {
                if (totalSize - totalReceived >= 1000)
                {
                    buffer = connection.recv_data(1000, p2pSocket);
                    received = 1000;
                    totalReceived += received;
                    writer.Write(buffer, 0, received);
                    Thread.Sleep(1);
                }
                else
                {
                    buffer = connection.recv_data(totalSize - totalReceived, p2pSocket);
                    received = totalSize - totalReceived;
                    totalReceived += received;
                    writer.Write(buffer, 0, received);
                    Thread.Sleep(1);
                }
                if (!Monitor.TryEnter(signal, 0))
                {
                    writer.Close();
                    try
                    {
                        File.Delete(user_dir + "/" + filename);
                    }
                    catch
                    {
                        MessageBox.Show("The file: " + filename + " could not be deleted.\r\nPlease delete it yourself.");
                    }
                    return false;
                }
                Monitor.Exit(signal);
                sic_.updateFileTransferWindow(senderUIN, (((float)totalReceived / (float)totalSize) * 100));
            }
            writer.Close();
            return true;
        }

Thank you for your help in advance...
Posted
Comments
hammerstein05 6-Jul-10 17:36pm    
Reason for my vote of 5
This is what a question should look like!

You seem to be making assumptions about the number of characters received in your recv_data() calls but nowhere do you check that you do actually receive that number of bytes. Thus what you write to disk may be only part of the message that was sent. You need to check exactly how many bytes you receive on each call, and only write that amount to disk. You could also do with some error checking.
 
Share this answer
 
First of all, thank you for your reply.
I'm sorry, I didn't mention that. The line
buffer = connection.recv_data(1000, p2pSocket);

does the following:
It receives exactly 1000 Bytes via the specified Socket (p2pSocket) and returns a byte-array to the caller. If less than the specified amount or nothing could be received, it returns null, what actually would cause my code to crash, as I see right now :-D
So, while I run trough the loop, checking if totalReceived < totalSize I always check, if the remaining filesize is less than 1000 bytes and, if it is, I just receive the missing bytes.
But before posting this, I just made a little test. I simply sent a file from a little server to a client and all worked fine. Maybe the code above isn't working, because I'm calling it within a thread instead of using the async methods... I'll give it a try with the async methods, when I return from work.
I'll give you a feedback, of what happened.
 
Share this answer
 
Comments
Richard MacCutchan 7-Jul-10 9:39am    
Are you absolutely certain that recv_data gets exactly 1000 bytes every time? I would be interested to see the code.
TickyTacky 8-Jul-10 3:28am    
Yes, I am. I'll post the code this evening, as I had no time to work on this project yesterday.
Right now I'm really getting mad about this... What I've done now, is using the Async Socket BeginReceive-Method, to receive the file. I created a little class, which does all the receiving for me. So, here is what the class looks like:

class AsyncFileRecv
{
    private long fileSize;
    private long received;
    private Socket recvSocket;
    private byte[] buffer;
    private BinaryWriter writer;
    private sic sic_;
    private string senderUIN;
    public bool done;
    private Object myLock = new Object();

    public AsyncFileRecv(long FileSize, Socket RecvSocket, BinaryWriter Writer, sic Sic_, string SenderUIN)
    {
        fileSize = FileSize;
        recvSocket = RecvSocket;
        writer = Writer;
        sic_ = Sic_;
        senderUIN = SenderUIN;
        received = 0;
        done = false;

        if (fileSize > 1000)
        {
            buffer = new byte[1000];
            recvSocket.BeginReceive(buffer, 0, 1000, SocketFlags.None, receive, null);
        }
        else
        {
            buffer = new byte[(int)fileSize];
            recvSocket.BeginReceive(buffer, 0, (int)fileSize, SocketFlags.None, endReceive, null);
        }
    }

    public void receive(IAsyncResult res)
    {
        if (res.IsCompleted)
        {
            received += 1000;

            lock (myLock)
            {
                writer.Write(buffer, 0, 1000);
            }

            sic_.updateFileTransferWindow(senderUIN, (((float)received / (float)fileSize) * 100));

            if ((fileSize - received) > 1000)
            {
                buffer = new byte[1000];
                recvSocket.BeginReceive(buffer, 0, 1000, SocketFlags.None, receive, null);
            }
            else
            {
                buffer = new byte[(int)(fileSize - received)];
                recvSocket.BeginReceive(buffer, 0, (int)(fileSize - received), SocketFlags.None, endReceive, null);
            }
        }
        else
        {
            MessageBox.Show("Async not completed - receive");
        }
    }

    public void endReceive(IAsyncResult res)
    {
        if (res.IsCompleted)
        {
            lock (myLock)
            {
                writer.Write(buffer, 0, (int)(fileSize - received));
            }

            received = fileSize;

            sic_.updateFileTransferWindow(senderUIN, (((float)received / (float)fileSize) * 100));

            done = true;

            writer.Close();
        }
        else
        {
            MessageBox.Show("Async not completed - endReceive");
        }
    }
}


Also I changed the code of the function recvFile as follows:

private bool recvFile(Socket tmpSocket, int TotalSize, string filename, string senderUIN, object signal)
{
    Socket p2pSocket = tmpSocket;
    int totalSize = TotalSize;
    byte[] buffer = new byte[1000];
    BinaryWriter writer;

    /* Wenn Directory noch nicht existiert, erstelllen */

    if (!System.IO.Directory.Exists(@"./Received Files"))
        System.IO.Directory.CreateDirectory(@"./Received Files");

    /* Userspezifisches verzeichnis */
    string user_dir = "./Received Files/" + uin;

    if (!System.IO.Directory.Exists(@user_dir))
        System.IO.Directory.CreateDirectory(@user_dir);

    writer = new BinaryWriter(File.Open(user_dir + "/" + filename, FileMode.Create));

    AsyncFileRecv fileRecv = new AsyncFileRecv(totalSize, p2pSocket, writer, sic_, senderUIN);

    while (!fileRecv.done)
    {
    }

    return true;
}


Yes, I know, the while (!fileRecv.done) isn't really well coded, but right now I just want this to work...
To give you a better impression of what my testfiles look like before and after sending, I uploaded them. All in all it's four files. Two images (one before and one after sending) and two textfiles. You can find them here:
click here for the testfiles[click here for new window]

Please regard, that you need to scroll sideways, to see all of the textfile after sending.

Again, thank you for your help in advance...

Edit: Because the method recvData isn't used anymore, I didn't post the code for that. I hope that's okay for you...

Edit 2: I'm not sure, if my answer did show that, but the problem still exists...

Edit 3: Not sure if this helps, but I recognized, that decreasing the buffer-size to 10 bytes makes the code work, altough the speed is extremely low...
 
Share this answer
 
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900