Модераторы: gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Передача файла через сеть, Прошу разобрать код и указать на недочет 
V
    Опции темы
Freak_FB
Дата 23.2.2010, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ктулхувед
**


Профиль
Группа: Участник
Сообщений: 296
Регистрация: 13.10.2006

Репутация: нет
Всего: 4



Решил плотно освоить тему работы с сетью в .NET. Остановился на передаче файлов через сеть.

Алгоритм такой: считываю файл в байтовый массив, высчитываю его длину и MD5 хеш.
Делаю коннект на сервер, передаю длину, хеш, затем блоками по 4096 байт передаю файл.

В общем - передача через раз заканчивается ошибкой. На той стороне хеш после сборки не совпадает.

Код клиента (только функция передачи):
Код

private void btnSend_Click(object sender, EventArgs e)
        {
            byte[] fileContents = File.ReadAllBytes(txtFileName.Text);
            byte[] hash = new MD5CryptoServiceProvider().ComputeHash(fileContents);

            txtLog.AppendText("Computed MD5 hash\n");
            txtLog.AppendText(string.Format("Hash is: {0}\n", MD5Lib.HashToString(hash)));

            try
            {
                using (TcpClient client = new TcpClient())
                {
                    client.SendBufferSize = client.ReceiveBufferSize = 4096;
                    client.Connect(txtIP.Text, 8080);
                    int fileSize = fileContents.Length;
                    byte[] fileSizeData = BitConverter.GetBytes(fileSize);
                    NetworkStream ns = client.GetStream();
                    ns.Write(fileSizeData, 0, fileSizeData.Length);
                    ns.Write(hash, 0, hash.Length);
                    ns.Flush();
                    int blockSize = client.SendBufferSize;
                    int blocksCount = (int)Math.Ceiling((float)fileSize / (float)blockSize);
                    int sentDataBytesCount = 0;
                    for (int i = 0; i < blocksCount; i++)
                    {
                        int packetSize = Math.Min(fileSize - sentDataBytesCount, blockSize);
                        ns.Write(fileContents, sentDataBytesCount, packetSize);
                        sentDataBytesCount += packetSize;
                        ns.Flush();
                    }
                    ns.Close();
                    client.Close();
                }
            }
            catch (Exception ex)
            {
                txtLog.AppendText(ex.Message.ToString() + "\n");
            }
        }


Код сервера:
Код

using System;
using System.Net.Sockets;
using System.IO;
using System.Security.Cryptography;
using System.Net;
using MD5Libs;

namespace Receiver
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Waiting for a file...");
                IPAddress local_addr = IPAddress.Parse("10.0.0.181");
                TcpListener listener = new TcpListener(local_addr, 8080);
                listener.Start();

                while (true)
                    while (listener.Pending())
                        listener.BeginAcceptTcpClient(ClientAccept, listener);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Ooops! {0}", ex.Message);
            }
            Console.ReadLine();
        }

        private static void ClientAccept(IAsyncResult ar)
        {
            TcpListener listener = (TcpListener)ar.AsyncState;

            TcpClient client = listener.EndAcceptTcpClient(ar);

            client.SendBufferSize =
                client.ReceiveBufferSize =
                4096;

            NetworkStream ns = client.GetStream();

            byte[] fileSizeData = new byte[4];
            ns.Read(fileSizeData, 0, fileSizeData.Length);

            int fileSize = BitConverter.ToInt32(fileSizeData, 0);
            Console.WriteLine("File size is: {0} bytes", fileSize);

            byte[] hashData = new byte[16];
            ns.Read(hashData, 0, hashData.Length);

            Console.WriteLine("Hash data received");
            Console.WriteLine("Hash: {0}", MD5Lib.HashToString(hashData));

            byte[] data = new byte[4096];
            byte[] fileContents = new byte[fileSize];

            int blockSize = client.ReceiveBufferSize;
            int blocksCount = (int)Math.Ceiling((float)fileSize / (float)blockSize);
            int rcvdDataBytesCount = 0;

            for (int i = 0; i < blocksCount; i++)
            {
                int packetSize = Math.Min(fileSize - rcvdDataBytesCount, blockSize);
                ns.Read(fileContents, rcvdDataBytesCount, packetSize);
                rcvdDataBytesCount += packetSize;
                Console.WriteLine("Received block #{0}", i + 1);
            }

            Console.WriteLine("All blocks received");

            byte[] checkHashData = new MD5CryptoServiceProvider().ComputeHash(fileContents);
            Console.WriteLine("Check hash: {0}", MD5Lib.HashToString(checkHashData));

            ns.Close();
            client.Close();

            if (HashesEqual(hashData, checkHashData))
            {
                Console.WriteLine("Hashes are equal");
                string fileName = @"c:\data.bin";
                File.WriteAllBytes(fileName, fileContents);
            }
            else
            {
                Console.WriteLine("Wrong hash data");
            }            
        }

        private static bool HashesEqual(byte[] hash1, byte[] hash2)
        {
            for (int i = 0; i < 16; i++)
                if (hash1[i] != hash2[i])
                    return false;
            return true;
        }
    }
}


Ошибка возникает при передаче на стороне клиента: соединение якобы закрывается сервером.
Укажите, какие ошибки я допустил в этом коде, как его можно улучшить, поделитесь своим опытом.
Заранее спасибо за внимание.


--------------------
user posted image
user posted image
Тонет Ктулху, все медведы горят в огне.
Я Креведко, очень страшно сегодня мне.

PM MAIL ICQ Skype GTalk Jabber   Вверх
Freak_FB
Дата 23.2.2010, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ктулхувед
**


Профиль
Группа: Участник
Сообщений: 296
Регистрация: 13.10.2006

Репутация: нет
Всего: 4



Никто ничего не посоветует?
Насчет того что бьются данные - выяснил. Выяснилось, что NetworkStream.Read вполне может и не считать весь положенный обьем байтов, поэтому следовало пользоваться возвращаемым значением этого метода. Поправил, всё работает без проблем.



--------------------
user posted image
user posted image
Тонет Ктулху, все медведы горят в огне.
Я Креведко, очень страшно сегодня мне.

PM MAIL ICQ Skype GTalk Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
cully
mr.DUDA
Exception

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, cully, mr.DUDA, Exception.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Распределённые приложения и сеть | Следующая тема »


 




[ Время генерации скрипта: 0.0437 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.