Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Получение бинарного файла через сокет (C#)


Автор: Lord Dagger 8.9.2005, 14:30
Здраствуйте! Я написал небольшую программу для загрузки файлов, но возникла следующая проблема: как отделить заголовок от данных?smile
Пока я делаю это простым парсингом:
Код

Socket connection = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
                IPHostEntry hostInfo = Dns.Resolve( TheUri.Host );
                IPEndPoint ep =  new IPEndPoint(hostInfo.AddressList[0] , TheUri.Port );
                connection.Connect( ep );


                //4. Sending request and reading response
                NetworkStream ns = new NetworkStream( connection,  FileAccess.ReadWrite );
                StreamReader strmReader = new StreamReader( ns ); 
                StreamWriter strmWriter = new StreamWriter( ns );

                byte[] buf = new byte[ 1000000 ];
                byte[] her = new byte[ 1000000 ];
                FileStream file = new FileStream( "exp.gif",FileMode.Create);
                BinaryWriter w = new BinaryWriter(file);

                strmWriter.Write( Head );
                strmWriter.Flush();

                // Чтение заголовка
                int bytes = 0;
                int state = 0;
                while (ns.Read( buf,0, connection.Available ) != -1)
                {
                    switch (buf[ bytes ])
                    {
                        case 13:
                            state++;
                            break;
                        case 10:
                            state++;
                            break;
                        default:
                            state = 0;
                            break;
                    }
                    if (state == 4)
                    {
                        Array.Copy(buf,bytes,her,0,1000000-bytes);
                        break;
                    }
                    bytes++;
                }
                
                bytes = 0;
                
                w.Write(her, 1, 312); // пока размер итогового файла задется вручную
            
                file.Flush();
                file.Close();

Но возникает проблема: скачиваемый файл не может быть больше размеров буфера.
Как преодолеть это?
MSDN читал, в google искал.
Нашел много всего хорошего, но не ответ на этот вопрос...
Буду очень благодарен за помощь!

Автор: Mad 8.9.2005, 14:39
Lord Dagger
1. Судя по коду, запрос этот ты на HTTP сервер шлеш. Но может и нет, так что укажи какой протокол
2. Если протокол HTTP, то лечше использовать WebRequest
3. Для приема произволной длины в памяти, используй MemoryStream

Автор: Lord Dagger 8.9.2005, 14:52
Mad
1. Да, протокол http
2. Этовроде бы другой уровень абстракции?
3. Это мне не нужно...
Если файл занимает 100 мб, то гораздно удобнее читать его порциями по 1 мб
Фактически, вопрос формулируется так:
Как правильно организовать считывание файла через network stream с использованием буфера, значительно меньше длины файла?

Автор: Mad 8.9.2005, 15:08
Цитата(Lord @ 8.9.2005, 13:52)
Да, протокол http

тогда у тебя и конец заголовка определяеться неправильно smile
каждая строка в заголовке ответа HTTP сервера заканчиваеться 13-13-10 а сам заголовок заканчиваеться 13-13-10-13-13-10

а код получаеться такой :

Код

                byte[] buf = new byte[ 4096 ];
                byte[] head = new byte[ 1000000 ];
                FileStream file = new FileStream( "exp.gif",FileMode.Create);
                BinaryWriter w = new BinaryWriter(file);

                strmWriter.Write( Head );
                strmWriter.Flush();

                // Чтение заголовка
                int bytes = 0;
                while (ns.Read( head, bytes, 1 ) != -1)
                {
                    if (bytes > 5 && head[bytes] = 10 && head[bytes-1] == 13 && head[bytes-2] == 13
                        && head[bytes-3] == 10 && head[bytes-4] == 13 && head[bytes-5] == 13)
                        break;
                    bytes++;
                }
                
                int readed = ns.Read(buf, 0, 4096);
                while (readed > -1)
                {                
                    w.Write(buf, 0, readed);
                    readed = ns.Read(buf, 0, 4096);
                }

                ns.Close();
                w.Close();

Автор: Lord Dagger 8.9.2005, 15:43
Mad
Спасибо, но код не работает... smile
Код

if (bytes > 5 && head[bytes] = 10 && head[bytes-1] == 13 && head[bytes-2] == 13
                        && head[bytes-3] == 10 && head[bytes-4] == 13 && head[bytes-5] == 13)

Приводит к:
(265): Operator '&&' cannot be applied to operands of type 'bool' and 'byte'

Если записать
Код

if ((bytes > 5 && head[bytes] == 10) && (head[bytes-1] == 13 && head[bytes-2] == 13)
                        && (head[bytes-3] == 10 && head[bytes-4] == 13) && head[bytes-5] == 13)

получается бесконечный цикл...

Автор: Mad 8.9.2005, 15:58
Цитата(Lord @ 8.9.2005, 14:43)
Operator '&&' cannot be applied to operands of type 'bool' and 'byte'

там просто опечатка получилась smile

Цитата(Lord @ 8.9.2005, 14:43)
получается бесконечный цикл...

модет винда делает маленькое преобразование, попробуй так

Код

if (bytes > 3 && head[bytes] == 10 && head[bytes-1] == 13 && head[bytes-2] == 10 && head[bytes-3] == 13) 

Автор: Lord Dagger 8.9.2005, 16:10
Mad
Получилось, теперь работает, но проблема здесь:
Код

                int readed = ns.Read(buf, 0, 4096);
                while (readed > -1)
                {                
                    w.Write(buf, 0, readed);
                    readed = ns.Read(buf, 0, 4096);
                }

readed всегда получает значение 0, когда считывание файла прекращается.
Везде в примерах тем не менее я видел -1 smile
что бы это значило?

P.S. Файл считывается нормально, только выполнение программы не прекращаетсяsmile

Автор: mr.DUDA 8.9.2005, 16:32
Цитата(Lord @ 8.9.2005, 16:10)
Везде в примерах тем не менее я видел -1
что бы это значило?

Скорее всего, это ошибка.

Автор: Lord Dagger 8.9.2005, 16:48
mr.DUDA
Ясно.. Спасибо всем за помощь, вы мне здорово помогли!
Неплохо было бы на будущее написать туториал в C# FAQ
Подобные есть, но под Java:
http://www.javable.com/columns/serv_side/workshop/18/

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)