Почему файлы не передаются (сохраняются?) Должным образом между клиентом в C # и сервером в C через tcp? - PullRequest
0 голосов
/ 25 января 2019

Я настроил TCP-клиент в C # и сервер в C. Когда я хочу передать файл, некоторые пакеты теряются и файл не сохраняется должным образом.

Я сравнил файл PDF, который пыталсяпередача и половина пакетов не были сохранены, поэтому я не смог открыть его на другом компьютере.

код клиента:

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.");
        }
    }

код сервера:

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;    
}

Как гарантировать, что каждый пакет будет сохранен правильно?

1 Ответ

0 голосов
/ 25 января 2019

Одна проблема с этой строкой:

fileFromClient << buff;

Это будет записывать содержимое buff, пока не будет найден нулевой байт.Поскольку вы передаете двоичный файл, вы можете ожидать, что эти байты будут частыми.Остальная часть полученного пакета не будет записана.

Вместо использования оператора << следует использовать

fileFromClient.write(buff, received);
...