Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/86: Рейтинг темы: голосов - 86, средняя оценка - 4.86
Noxx
1

Передача файла через сокет

10.12.2011, 05:02. Показов 16665. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Итак... у меня сложилась одна затруднительная ситуация. Есть сервер, есть клиент. С передает К файл посредством
C#
1
client.SendFile(filename, null, null, TransmitFileOptions.UseDefaultWorkerThread);
клиент принимает

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   MemoryStream memstr = new MemoryStream();
                FileStream fs = File.Create(package_name);
 
                while (true)
                {
                    buffer = new byte[4096];
                    int o = server.Receive(buffer);
                    if (o == 0)
                    {
                        break;
                    }
                    memstr.Write(buffer, 0, buffer.Length);
                }
                memstr.WriteTo(fs);
                fs.Close();
                memstr.Close();
в итоге получаем файл с большим размером, чем оригинал... ну ладн, это несложно преодолеть написав

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// size - это размер файла
MemoryStream memstr = new MemoryStream();
                FileStream fs = File.Create(package_name);
                long received = 0;
                while (true)
                {
                    if (received + 4096 > size)
                    {
                        buffer = new byte[size-received];
                        server.Receive(buffer);  
                        memstr.Write(buffer, 0, buffer.Length);
                        break;
                    }
                    buffer = new byte[4096];
                    server.Receive(buffer);
                    received = received + 4096;
                    memstr.Write(buffer, 0, buffer.Length);
                }
                memstr.WriteTo(fs);
                fs.Close();
                memstr.Close();
получаем на выходе файл аналогичного размера, что и оригинал, НО он не запускается. Если же сделать буфер равный 1 байту, то на выходе получается рабочий файл. Но это цикл на 4 млн проходов при файле в 4 мб. это нехорошо...

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
MemoryStream memstr = new MemoryStream();
                FileStream fs = File.Create(package_name);
 
                while (true)
                {
                    buffer = new byte[1];
                    int o = server.Receive(buffer);
                    if (o == 0)
                    {
                        break;
                    }
                    memstr.Write(buffer, 0, buffer.Length);
                }
                memstr.WriteTo(fs);
                fs.Close();
                memstr.Close();
Может кто объяснить почему так? И как исправить эту проблему.

Если честно сутки просидел над этими 10 строчками кода, но так и не понял почему файл получается нерабочим во 2 варианте
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.12.2011, 05:02
Ответы с готовыми решениями:

Передача значений переменных через сокет
Добрый всем вечер. Вопрос: имеется клиент, он должен передать серверу 4 переменных. Сервер должен...

пересылка файла через сокет
Добрый день! Перейду сразу к делу - в нете полно примеров как пересылать файл с одной папки в...

Отправка сообщения через сокет
какой метод отправки сообщения через сокет (с сервера) самый эффективный??? Добавлено через 1...

Вывод строк через сокет
Всем привет. Пытаюсь вывести сообщения через асинхронные сокеты, чтобы клиент, подключившись через...

6
T34
21.12.2011, 14:17 2
надо послать текстовый файл с содержанием 1234567890123456.... и так далее
и проверить пришедший файл. после этого понять что происходит. То что вы просто отрезали кусок файла по размеру не означает что вы отрезали что надо и не пропустили что не надо).

бывают варианты.
не хватает величины приемного буфера и данные теряются. надо слать пакетами.
неправильно интерпретируется файл, то есть вы посылаете бинарный файл а посылается он как текстовый и соответственно каждый встреченный символ 0x0d дополняется символом 0x0A конец строки - возврат каретки.

В вашем случае есть еще такая фигня при работе с потоками отдание приказа послать и посылка - разные вещи. посмотрите в сторону функции flush, она принудительно заставляет перепихать буфер потока туда куда он его пихал и очистить буфер.
Noxx
21.12.2011, 23:14 3
я проверил бинарным редактором принятый файл, получилось что посреди файла встречаются в случайном порядке блоки размером с буфер приема, в которых все биты имеют значение 0
T34
22.12.2011, 10:48 4
тогда надо на принимающей стороне найти признак буфер готово. Наверное вы запускаете процедуру чтения когда буфер пустой и поток возвращает нулевой буфер и признак ошибки, а вы этот факт пропускаете и принимаете буфер как полный... или что-то типа того.

хуже было бы если бы были случайные кропления нулей.. или просто какой то белеберды...
Noxx
18.01.2012, 20:51 5
да, спасибо. вроде как раз то, что нужно. Буфер не успевал заполняться до того, как я начинал записывать этот буфер в поток. отсюда и случайные блоки пустых битов.
Noxx
18.01.2012, 21:25 6
вот, вдруг кому понадобится

Клиент
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//удаляем существующий файл
if (File.Exists("1.mp3") == true)
            {
                File.Delete("1.mp3");
            }
// открываем поток для сохранения принятого файла
            FileStream file = new FileStream("1.mp3", FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None);
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// слушаем входящее подключение
            server.Connect(ipep);
 
            while (true)
            {
// если есть доступные данные, которые всецело можно записать в буфер обмена - то пишем
                if (server.Available > 4096)
                {
                    byte[] data = new byte[4096];
                    int recv = server.Receive(data, SocketFlags.None);
                    if (recv == 0)
                        break;
                    file.Write(data, 0, data.Length);
                }
//иначе проверяем, является ли это последним блоком данных, который меньше нашего буфера
                else
                {
                    // 5402624 - размер файла оригинала
                    if (file.Length + server.Available == 5402624)
                    {
                        byte[] data = new byte[4096];
                        server.Receive(data, SocketFlags.None);
                        file.Write(data, 0, data.Length);
                        break;
                    }
                }
// если нет подходящих условий - то ничего не делаем, пока собственно буфер приема не заполнится
 
            }
            server.Shutdown(SocketShutdown.Both);
            server.Close();
Сервер
C#
1
2
3
4
5
6
7
8
9
10
11
12
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
            Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            newsock.Bind(ipep);
            newsock.Listen(10);
            Console.WriteLine("Waiting for a client...");
            Socket client = newsock.Accept();
            IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
            Console.WriteLine("Connected with {0} at port {1}", clientep.Address, clientep.Port);
            client.SendFile("1.mp3");            
            Console.WriteLine("Disconnected from {0}", clientep.Address);
            client.Close();
            newsock.Close();
2 / 2 / 0
Регистрация: 01.12.2014
Сообщений: 32
18.12.2015, 00:57 7
Все равно ошибка есть. нужно так:
C#
1
file.Write(data, 0, recv);
0
18.12.2015, 00:57
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.12.2015, 00:57
Помогаю со студенческими работами здесь

Ошибка соединения через сокет
Вот такую ошибку выдает клиентское приложение: " запрос на отправку или получение данных (when...

Как передать массив через сокет?
Подскажите пожалуйста. Нужно реализовать игру крестики нолики, клиент-сервер. Здесь я могу...

Повторное подключение к серверу через сокет
Здравствуйте, долго сижу на одном месте и никак не могу сделать додуматься в чем проблема. У меня...

Как передать массив через сокет?
Подскажите как передать массив через сокет? Часть кода: byte sdata = null; sdata =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru