• XSS.stack #1 – первый литературный журнал от юзеров форума

[ ? ] Rust + Winsock

VVS

1917
Premium
Регистрация
08.11.2020
Сообщения
49
Реакции
30
Гарант сделки
1
Привет форумчане)
Ломаю голову, не могу найти решения никак

Делаю Get запрос, в надежде получить ответом бинарный файл (recv)
Читаю в цикле пока не равно нулю
(Пробовал вызывать первый раз функцию и из первого ответа брать число сколько надо читать, но тогда файл почему-то записывается где-то без четверти с конца [так же как и резать его по тому же размеру])
по итогу получается вот какая картина:
[ + ] Оригинальный конец файла выглядит так:

orig.png


[ - ] То что я получаю выглядит вот так:

me.png


то есть, будто бы дописывает несколько раз конец
при том длина буфера после чтения в него данных каждый раз разная
Таблица импорта в таком файле выглядит примерно так:

т_и.png

я думаю вопрос с получением нуль терминированных символов но это не точно

так же делал пару тестов с получением хтмл страницы, вроде все норм

сокетоводы, отпишитесь плз)
 
Тебе функция RECV возвращает количество полученных байт, попробуй вызвать RECV получи кол-во байт. Http заголовки от данных будут отделены \r\n\r\n - это байты (0x0D,0x0A,0x0D,0x0A) всё что идёт после 0x0D,0x0A,0x0D,0x0A будет payload'ом. Ну или можешь прочитать только то количество байт которое тебе вернул заголовок Content-Length
 
Тебе функция RECV возвращает количество полученных байт, попробуй вызвать RECV получи кол-во байт. Http заголовки от данных будут отделены \r\n\r\n - это байты (0x0D,0x0A,0x0D,0x0A) всё что идёт после 0x0D,0x0A,0x0D,0x0A будет payload'ом. Ну или можешь прочитать только то количество байт которое тебе вернул заголовок Content-Length
я так и делаю, но в самом низу несколько раз дописывается конец (пример выше)
Если читаю то количество байт, которое вернул Content-Length - файл записывается без четверти (где-то) с конца
Пробовал даже:
[(Content-Length - длина http заголовка)..(Content-Length + длина http заголовка]
 
Пожалуйста, обратите внимание, что пользователь заблокирован
сокетоводы, отпишитесь плз)
Ты код покажи, или хотя бы псевдокод. иначе это угадывание.
 
Ты код покажи, или хотя бы псевдокод. иначе это угадывание.
Код:
    const DEFAULT_BUFLEN: i32 = 512;

    let mut bytes_to_read: i32 = 0;
    let mut bytes_to_write: i32 = 0;

    let mut recv_buf_2: Vec<u8> = Vec::new();
            recv_buf_2.resize(DEFAULT_BUFLEN as usize, 0u8);

    let mut recv_buf_3: Vec<u8> = Vec::new();

    nret = recv(the_socket, recv_buf_2.as_ptr() as *mut i8, DEFAULT_BUFLEN.try_into().unwrap(), 0);

    recv_buf_3.append(&mut recv_buf_2.clone().into());
    bytes_to_write += nret;

    let reader = String::from_utf8_lossy(&recv_buf_3);
    
    for (_, line) in reader.lines().enumerate()
    {
        let line = line;
        if line.contains("200")
        {
            println!("[ + ] Status is {:?}", line);
            continue;
        };

        if line.contains("Content-Length: ")
        {

            let content_length = &line.rfind("Content-Length: ").unwrap();
            let get_length = &line[*content_length +16..line.len()].trim();

            if !get_length.is_empty()
            {
                bytes_to_read = get_length.parse::<i32>().unwrap();
                println!("Length is: {:?}", get_length);
            };

        };
    };

    loop
        {

            if nret > 0
            {

                nret = recv(the_socket, recv_buf_2.as_ptr() as *mut i8, DEFAULT_BUFLEN.try_into().unwrap(), 0);

                recv_buf_3.append(&mut recv_buf_2.clone().into());
                bytes_to_write += nret;

            } else if nret == 0
            {

                println!("End Recieve: {}", recv_buf_3.len());
                closesocket(the_socket);
                break;

            } else if nret < 0
            {

                closesocket(the_socket);
                println!("Recv() Socket Closed. So We're Done!\n"); break;

            } else
            {
                println!("recv failed with error: {:?}\n", WSAGetLastError());
            }

        }
        
    let new_buf = &recv_buf_3[253..recv_buf_3.len()]; // 253 это начало мз

    let mut create = std::fs::File::create("C:\\file.txt").unwrap();
    create.write(&new_buf).unwrap();
 
Код:
     // const DEFAULT_BUFLEN: i32 = 512; // Норм, хотя не оч: "Х@ли тут так мало?"
     const DEF_BUF_SIZE: usize = 1024 * 8 // Хотя бы 8KB то накинь шеф.

     // let mut bytes_to_read: i32 = 0; // Мы не собираемся читать 0 байт.
     // let mut bytes_to_write: i32 = 0;
     let mut bytes_to_write = 0usize;
     let mut received = 0uszie;


     // let mut recv_buf_2: Vec<u8> = Vec::new();
     //       recv_buf_2.resize(DEFAULT_BUFLEN as usize, 0u8); // Нельзя шутить с векторами в Rust для буфферов, забудешь его аллоцировать (а точнее инициализировать нулями)
     // огребешь по полной, Rust не аллоцирует память по умолчанию для вектора...
     // Куда так спешишь, брат, на куче аллоцировать, брат? Давай лучше на стэке, брат.
    let mut tmp_buf = [0u8; DEF_BUF_SIZE];

    // let mut recv_buf_3: Vec<u8> = Vec::new();
    let mut buf = Vec::new(); // Отдайся тайп инференсу, он все сделает сам, глупенький.

    // nret = recv(the_socket, recv_buf_2.as_ptr() as *mut i8, DEFAULT_BUFLEN.try_into().unwrap(), 0);
    let amt = recv(the_socket, tmp_buf.as_mut_ptr() as *mut 8, DEF_BUF_LEN, 0); // Вероятно уже отпадет потребность кастить DEF_BUF_LEN, но если в большую байтность или туже, используй `as` (не ссы косякнуть, компилятор добрый, но не простит) и не ври компилятору, ты собрался модифицировать буфер.

    // recv_buf_3.append(&mut recv_buf_2.clone().into()); // Ничего что ты прочитал amt количество байт, а пишешь весь буфер (нули решил почитать?), да еще и клонировать его зачем-то решил...
    buf.extend_from_slice(&tmp_buf[..amt]);
    // bytes_to_write += nret;
    bytes_to_write += amt;

    let reader = String::from_utf8_lossy(&recv_buf_3);
 
    // for (_, line) in reader.lines().enumerate() // Орнул, ты зачем все в итератор превратил по индексу и строкам если ты не используешь индкесы?
    for line in reader.lines()
    {
        // let line = line; // За что?! Жалуется на move семантику? Тогда делай &line.contains(..)
        if line.contains("200")
        {
            println!("[ + ] Status is {:?}", line);
            continue;
        };

        if line.contains("Content-Length: ")
        {

            let content_length = &line.rfind("Content-Length: ").unwrap();
            // let get_length = &line[*content_length +16..line.len()].trim(); // Н-е-н-а-д-о line.len(), content_length – число тут, а не ссылка на него, с числами можно делать что хочешь, они неявно копируются – всегда, см. trait Copy.
            let get_length = &line[content_length +16..].trim();
            // if !get_length.is_empty() // А если нет, че делать будем?
            // {
            //    bytes_to_read = get_length.parse::<i32>().unwrap();
            //    println!("Length is: {:?}", get_length);
            // };
            if let Ok(length) = get_length.parse::<i32>() {
                 readed += length;
            } else {
                panic!("Все пропало");
            }
        };

        // Твоя задача не прочитать все что в буффере, а аккуратно прочитать все до конца заголовка...
        // И не забудь, ты читал буффер, у него нет никаких курсоров, вероятно ты не хочешь читать тоже самое?
        // Тогда избавься от того что прочитал и не потеряй то, что не прочитал (Конфуций (с)).
    };

    loop
        {

            if nret > 0
            {

                nret = recv(the_socket, recv_buf_2.as_ptr() as *mut i8, DEFAULT_BUFLEN.try_into().unwrap(), 0);

                recv_buf_3.append(&mut recv_buf_2.clone().into());
                bytes_to_write += nret;

            } else if nret == 0
            {

                println!("End Recieve: {}", recv_buf_3.len());
                closesocket(the_socket);
                break;

            } else if nret < 0
            {

                closesocket(the_socket);
                println!("Recv() Socket Closed. So We're Done!\n"); break;

            } else // <0, >0, == 0, Ты какие-то еще варианты ожидаешь?!
            {
                println!("recv failed with error: {:?}\n", WSAGetLastError());
            }
            // Не хочешь про@бать какое-то из потенциальных значений?
            // Доверься механизму  match exhaustive, компилятор тебя ткнет если что-то упустил.
         match nret.cmp(&0){
            Ordering::Less => ...,
            Ordering::Greater => ...,
            Ordering::Equal => ...,
          }
        }
    
    let new_buf = &recv_buf_3[253..recv_buf_3.len()]; // 253 это начало мз

    let mut create = std::fs::File::create("C:\\file.txt").unwrap();
    // create.write(&new_buf).unwrap(); // Так не делай, записаться мог не весь буфер, а только часть, а ты проигнорил, это не по пацански.
    create.write_all(&new_buf).expect("Файл должен записаться")


Код рабочим не стал, но мыслей я тебе накидал...

1. Читаешь заголовок до длины файла, запоминаешь длину файла.
2. Дочитываешь все до разделителя заголовка и тела (до конца заголовка).
3. Читаешь свой файл
Код:
let file_length = 100;
while file_length != 0 {
    let amt = socket.read(...);
    file_length -= amt;
}
4. Аккуратненько пишешь файл.
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх