appendix
appendix

Reputation: 127

Why files are not transfered (saved?) properly between client in C# and server in C via tcp?

I've set up TCP client in C# and server in C. When I want to transfer file, some packets are lost and file is not saved properly.

I've compared PDF file I tried to transfer and half of packets were not saved, so I couldn't open it on another computer.

client code:

public void SendFile(string file, string destPath = "C:\\")
    {
        int bufferSize = 1024;
        byte[] filebuff = new byte[bufferSize];
        string fileName = destPath + file;

        //send to TcpServer request to send file
        stream.Write(textToBytes("RECEIVEFILE"), 0, 11);
        try
        {
            FileStream streamFile = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            BinaryReader binReader = new BinaryReader(streamFile);


            //send file name to TcpServer
            stream.Write(textToBytes(file), 0, file.Length);


            //get file size
            long filesize = streamFile.Length;

            //send file size to TcpServer
           //sendData(stream, BitConverter.GetBytes(filesize));

            //if file doesn't exist
            if (file == null)
            {
                Console.WriteLine("Error.");
            }

            //if file is empty
            if (filesize == 0)
            {
                Console.WriteLine("File size: 0");
                return;
            }


            int totalLength = Convert.ToInt32(filesize);

            Console.WriteLine("Totallength: " + totalLength);
            long numberOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(streamFile.Length) / bufferSize));
            int currentPacketLength;

            for (int i = 0; i < numberOfPackets; i++)
            {
                if (filesize > bufferSize)
                {
                    currentPacketLength = bufferSize;
                    totalLength = totalLength - currentPacketLength;
                }
                else
                    currentPacketLength = totalLength;

                filebuff = new byte[currentPacketLength];
                //streamFile.Read(filebuff, 0, currentPacketLength);
                binReader.Read(filebuff, 0, currentPacketLength);


                stream.Write(filebuff, 0, filebuff.Length);
            }

            streamFile.Close();
        }
        catch
        {
            Console.WriteLine("There's no file...");
        }


    }

    public void DownloadFile(string fileName)
    {
        byte[] recBuffer = new byte[1024];
        byte[] fileNameBytes;
        long received = 0;
        long receivedAll = 0;
        byte[] fileData = new byte[1024];

        stream.Write(textToBytes("SENDFILE"), 0, 8);
        fileNameBytes = Encoding.UTF8.GetBytes(fileName);

        stream.Write(fileNameBytes, 0, fileNameBytes.Length);
        byte[] fileSizeBytes = new byte[4];
        stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);
        int bytes = BitConverter.ToInt32(fileSizeBytes, 0);

        Console.WriteLine("I'm downloading file...");

        while (receivedAll < bytes)
        {
            received = stream.Read(fileData, 0, fileData.Length);
            if (received < 0)
            {
                Console.WriteLine("Error");
                break;
            }
            BinaryWriter bWrite = new BinaryWriter(File.Open("C:\\" + fileName, FileMode.Append));
            bWrite.Write(fileData);
            bWrite.Close();
            receivedAll += received;

        }

        if(receivedAll == bytes)
        {
            Console.WriteLine("File downloaded successfuly.");
        }
    }

server code:

void ReceiveFile(int client_socket)
{
const int buffsize = 1024;
char buff[buffsize];
long filesize, received = 0, receivedall;
char filenamechar[512];

std::string filename, fullFilename;
memset(filenamechar, 0, 512);
 /*
    if(recv(client_socket, filenamechar, 512, 0) != 512)
{
    printf("Error - filename.\n");
    return;
}

fullFilename = "/Users/xxx/" + std::string(filenamechar);

*
if(recv(client_socket, &filesize, sizeof(long), 0) != sizeof(long))
{
    printf("Child process: error.\n");
    return;
}*/

filesize = 331776;

std::fstream fileFromClient;

fullFilename = "/Users/xxx/sockets.pdf";

fileFromClient.open(fullFilename, std::ios::binary | std::ios::out);

receivedall = 0;
while (receivedall < filesize)
{
    memset(buff, 0, 1024);
    received = recv(client_socket, buff, 1024, 0);
    if(received <= 0)
    {
        std::cout << "error" << std::endl;
        break;
    }
    receivedall += received;

    fileFromClient << buff;
    fputs(buff, stdout);
}

fileFromClient.close();

std::cout << "\nreceivedall: " << receivedall << std::endl;
std::cout << "filesize: " << filesize << std::endl;
if(receivedall != filesize)
    printf("Error\n");
else
    printf("File saved successfuly\n");

}

void SendFile(int client_socket)
{
char path[512];
char fileName[512];
char fullFileName[512];
long fileLen, sent, sentAll, read;
struct stat fileinfo;
FILE* file;
unsigned char bufor[1024];

memset(path, 0, 512);
strcpy(path, "/Users/xxxx/");

if (recv(client_socket, fileName, 512, 0) <= 0)
{
    printf("Child process: error\n");
    return;
}

strcpy(fullFileName, strcat(path, fileName));
printf("Child process: client wants file: %s\n", fullFileName);


if (stat(fullFileName, &fileinfo) < 0)
{
    printf("Child process: can't get file info\n");
    return;
}

if (fileinfo.st_size == 0)
{
    printf("Child process: file size: 0\n");
    return;
}

fileLen = fileinfo.st_size;

if (send(client_socket, &fileLen, sizeof(long), 0) != sizeof(long))
{
    printf("Child process: error\n");
    return;
}

sentAll = 0;
file = fopen(fullFileName, "rb");
if (file == NULL)
{
    printf("Error\n");
    return;
}

while (sentAll < fileLen)
{
    read = fread(bufor, 1, 1024, file);
    sent = send(client_socket, bufor, read, 0);
    if (read != sent)
        break;
    sentAll += sent;
    printf("Child process: sent %ld bytes\n", sentAll);
}

if (sentAll == fileLen)
    printf("Child process: file sent successfuly\n");
else
    printf("Child process: error\n");
fclose(file);
return;    
}

How to guarantee that each packet will be saved properly?

Upvotes: 0

Views: 84

Answers (1)

1201ProgramAlarm
1201ProgramAlarm

Reputation: 32727

One problem is with this line:

fileFromClient << buff;

This will write out the contents of buff until a zero byte is found. Since your are transferring a binary file, you can expect these bytes to be frequent. The rest of the received packet will not be written.

Rather than using the << operator, you should use

fileFromClient.write(buff, received);

Upvotes: 1

Related Questions