Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Просто загрузить и вывести txt файл по http


Автор: Валерия 25.4.2008, 21:13
Интересует аналог
Код

<?
readfile("http://ya.ru");
?>

На C++ ©
Под никсы.

Автор: bilbobagginz 25.4.2008, 21:22
если вопрос о програмном перекаче - выбирается нужная библиотека, и на ней катаешься. напр. libcurl (она на C, но есть какая-то бета для C++ - curlcpp )
если просто командой нужно притащить файл, смотри следующий совет.



Автор: JackYF 25.4.2008, 21:23
netcat

Добавлено через 17 секунд
`wget <url> -O-`

Автор: Валерия 25.4.2008, 21:37
А из чегото стандартного, что бы не ставить дополнительно библиотек?

Автор: MAKCim 25.4.2008, 22:01
Цитата(Валерия @  25.4.2008,  21:37 Найти цитируемый пост)
А из чегото стандартного, что бы не ставить дополнительно библиотек? 

а из стандартного только сокеты домена AF_INET типа SOCK_STREAM
но в этом случае тебе будет нужно самой формировать HTTP-запрос

Автор: Валерия 25.4.2008, 22:06
Спасибо smile
Та формирывать мне влень, просто со сниффера http заголовков скопирую, уже fsockopen/fputs/fgets в php юзала smile
А можно примерчик или сцылочку?)
А то я находила максимум как просто подсоедениться кудато на какойто айпи и порт и всё)

Автор: bilbobagginz 25.4.2008, 22:20
Цитата(Валерия @  25.4.2008,  22:06 Найти цитируемый пост)
А можно примерчик или сцылочку?)

качай libcurl, и там есть примерчиков по самое не хочу.
также есть программка wget, её сорс тоже можно скачать (open source)


Автор: MAKCim 25.4.2008, 22:26
Цитата(Валерия @  25.4.2008,  22:06 Найти цитируемый пост)
А можно примерчик или сцылочку?)

Код

struct sockaddr_in addr;
struct hostent * hostent;
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
hostent = gethostbyname("ya.ru");
addr.sin_addr.s_addr = *(u_int32_t*)hostent -> h_addr;
connect(socket_fd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in));
/* формируем HTTP-запрос в buffer */
char buffer[4096];
size_t size;
...
write(socket_fd, buffer, size); /* запрос */
read(socket_fd, buffer, 4096); /* получение ответа */


Автор: Валерия 25.4.2008, 23:51
Делаю так.
Код

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>



int main(){
 

struct sockaddr_in addr;
struct hostent * hostent;
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
hostent = gethostbyname("ya.ru");
addr.sin_addr.s_addr = *(u_int32_t*)hostent -> h_addr;
connect(socket_fd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in));

char buffer[4096] = "GET / HTTP/1.1\r\nHost: ya.ru\r\nUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12\r\nAccept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\nAccept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3\r\nAccept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 300\r\nConnection: keep-alive\r\nIf-Modified-Since: Thu, 20 Mar 2008 15:25:24 GMT\r\nCache-Control: max-age=0\r\n\r\n";
char buffer2[4096];

write(socket_fd, buffer, 4096);
read(socket_fd, buffer2, 4096);
printf("%s", buffer2);

return 0;
}

Но всё зависает нафик, причем если не делаю read то норм заканчиваеться. Т.е не выходит вытянуть ответ.

Автор: MAKCim 26.4.2008, 00:22
Валерия, 
Код

write(socket_fd, buffer, strlen(buffer));
read(socket_fd, buffer2, 4096);
printf("%s", buffer2);


Автор: Валерия 26.4.2008, 01:25
Спасибо, я до этого использовала сайз оф
А какая функция альтернативы feof для сокетов?
Т.е мне нужно в буфер забрасывать по 4096 пока не дойдет до конца

Автор: MAKCim 26.4.2008, 09:33
Цитата(Валерия @  26.4.2008,  01:25 Найти цитируемый пост)
А какая функция альтернативы feof для сокетов?

read() возвращает 0
Цитата(Валерия @  26.4.2008,  01:25 Найти цитируемый пост)
Т.е мне нужно в буфер забрасывать по 4096 пока не дойдет до конца 

в рамках одного HTTP-запроса?

Автор: GrayCardinal 26.4.2008, 16:30
Валерия, 
Для сокетов лучше юзать send/recv

Добавлено через 10 минут и 17 секунд
Далее.
Нельзя писать ВЕСЬ буфер. Нужно посчитать длину строки (strlen) и записывать полученное количество байт. Плюс я ещё бы добавил shutdown, но это на любителя...

Добавлено через 13 минут и 27 секунд
Да, ещё, для HTTP/1.1 простого чтения ответа недостаточно. Там есть такая вещь, как "кусочковая передача" (извините, не знаю как по-русски "chunked" smile )

Автор: Валерия 26.4.2008, 21:53
Цитата(MAKCim @  26.4.2008,  09:33 Найти цитируемый пост)
в рамках одного HTTP-запроса?

да.
Цитата(GrayCardinal @  26.4.2008,  16:30 Найти цитируемый пост)
Для сокетов лучше юзать send/recv

чем лучше?

Автор: MAKCim 26.4.2008, 22:19
Цитата(Валерия @  26.4.2008,  21:53 Найти цитируемый пост)
да.

Код

int flags = MSG_MORE;
while (1) {
    if (<все передали>)
        break;
    send(socket_fd, <данные>, <размер данных>, flags);
    if (<осталось вызвать send один раз>)
        flags = 0;
}



Автор: GrayCardinal 27.4.2008, 12:38
Валерия, 
Тем что они для этого предназначены smile

Автор: Валерия 27.4.2008, 14:35
Так что поповоду того что бы вывести не 4096 байт а все?
Даже если я подряд пишу несколько раз read  - выводит одно и тоже, заголовок и кусочек html

Автор: MAKCim 27.4.2008, 16:37
Цитата(Валерия @  27.4.2008,  14:35 Найти цитируемый пост)
Так что поповоду того что бы вывести не 4096 байт а все?

Код

ssize_t size;
while ((size = read(socket_fd, buffer2, 4096)) > 0)
    write(STDOUT_FILENO, buffer2, size);

Автор: Валерия 27.4.2008, 19:49
Разобралась, всем спасибо, особенно MAKCim))
Еще такой вопрос в догонку, если я не знаю сколько будет весить страничка, то что бы не выделять сильно много буфера, как при каждом записывании n байт в него, всё время увеличивать значение all?

Автор: MAKCim 27.4.2008, 20:19
Цитата(Валерия @  27.4.2008,  19:49 Найти цитируемый пост)
как при каждом записывании n байт в него, всё время увеличивать значение all? 

что за all?
что за буфер?

Автор: Валерия 27.4.2008, 21:19
Цитата(MAKCim @  27.4.2008,  20:19 Найти цитируемый пост)
что за all?что за буфер?

Упс, я до этого сообщение набрала что не получалось, но потом сама разобралась и не отправила smile
Код

    char host[] = "ya.ru";
    char path[] = "/";

    struct sockaddr_in addr;
    struct hostent * hostent;
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(80);
    hostent = gethostbyname(host);
    addr.sin_addr.s_addr = *(u_int32_t*)hostent -> h_addr;
    connect(socket_fd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in));


    char all[100000] = "";
    char buffer[4096] = "";
    strcat(buffer, "GET ");
    strcat(buffer, path);
    strcat(buffer, " HTTP/1.1\r\n");
    strcat(buffer, "Host: ");
    strcat(buffer, host);
    strcat(buffer, "\r\n\r\n");

    char buffer2[4096]; 

    ssize_t size;
    send(socket_fd, buffer, strlen(buffer), 0);

    while ((size = recv(socket_fd, buffer2, 4096, 0)) > 0 ){
        strcat(all, buffer2);
    }
    printf("%s", all);
    return 0;

Так вот, если я пишу all[100000] то выделяет 100 кб под это дело, а мне нужно что бы переменная all по мере забития в неё bufer2 постоянно увеличивалась)
Да и оператор new не пашет(
Для него подключать нужно что то?
И вообще, лучше всего киньте ссылкой на е-книгу на русском по программингу под линукс, а то я раньше писала под dos на турбо си, так не всё катит здесь что катило там...

Автор: MAKCim 28.4.2008, 09:02
Цитата(Валерия @  27.4.2008,  21:19 Найти цитируемый пост)
Так вот, если я пишу all[100000] то выделяет 100 кб под это дело, а мне нужно что бы переменная all по мере забития в неё bufer2 постоянно увеличивалась)

обязательно все данные записывать в массив?
можно по мере их поступления осуществлять вывод

Цитата(Валерия @  27.4.2008,  21:19 Найти цитируемый пост)
Да и оператор new не пашет(

да ну?  smile 

используй malloc() и связный список буферов
Цитата(Валерия @  27.4.2008,  21:19 Найти цитируемый пост)
И вообще, лучше всего киньте ссылкой на е-книгу на русском по программингу под линукс, а то я раньше писала под dos на турбо си, так не всё катит здесь что катило там... 

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

Автор: GrayCardinal 28.4.2008, 09:47
Валерия, 
1. В данном случае нельзя юзать strcat
2. Да и оператор new не пашет
Скорее всего используется gcc (Си компилер), вместо g++ (Си++ компилер).
3 Так вот, если я пишу all[100000] то выделяет 100 кб под это дело, а мне нужно что бы переменная all по мере забития в неё bufer2 постоянно увеличивалась)
Кто мешает написать примитивную функтяру изменения размера с сохранением данных ? 
Я, правда, в данном случае (HTTP GET) просто использовал временный файл.

Цитата

используй malloc() и связный список буферов

Тоже вариант.

Автор: GrayCardinal 28.4.2008, 11:11
ЗЫ
код возврата системных вызовов лучше всё-таки проверять smile

Автор: Валерия 28.4.2008, 18:03
Спасибо smile
Тут кстати проблемка возникла:

Код

            struct sockaddr_in addr;
    struct hostent * hostent;
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(80);
    hostent = gethostbyname(host);
    addr.sin_addr.s_addr = *(u_int32_t*)hostent -> h_addr;
    connect(socket_fd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in));

    char big[100000]="";
    char request[4096] = "";
    strcat(request, "GET ");
    strcat(request, path);
    strcat(request, " HTTP/1.1\r\n");
    strcat(request, "Host: ");
    strcat(request, host);
    strcat(request, "\r\n\r\n");

    char buffer2[4096]; 

    ssize_t size;
    send(socket_fd, request, strlen(request), 0);

    while ((size = recv(socket_fd, buffer2, 4096, 0)) > 0 ){
        strcat(big, buffer2);
    }


Работает но с багом, если страница больше 4х килобайт, то последний блок два раза запишет в big.

Добавлено через 5 минут и 39 секунд
И кстати, есть под си какаято библиотека с нормальной работой строк?
Ну тоесть

string mystr;
string s="dddd";
mystr = "abb" + s + "bbb";
типа такого)

Автор: MAKCim 28.4.2008, 18:20
Цитата(Валерия @  28.4.2008,  18:03 Найти цитируемый пост)
Работает но с багом, если страница больше 4х килобайт, то последний блок два раза запишет в big.

на каждой итерации нужно записывать в big size байт
Код

void * ptr = big;
while ((size = recv(socket_fd, buffer2, 4096, 0)) > 0 ){
        memcpy(ptr, buffer2, size);
        ptr += size;
}
*(char*)ptr = '\0';

Автор: JackYF 28.4.2008, 19:52
Цитата(Валерия @  28.4.2008,  17:03 Найти цитируемый пост)
mystr = "abb" + s + "bbb";
типа такого) 

в Си нет объектов и перегрузки операторов smile

Автор: kirjanov 28.4.2008, 21:15
Цитата(JackYF @  28.4.2008,  19:52 Найти цитируемый пост)
в Си нет объектов

А поименованную область памяти в C можно назвать объектом?)

string можно и через препроцессор сделать, а вместо '+' макрос добавить с подходящим именем smile

Автор: quasi 6.5.2008, 13:21
А как получить файлики определенного типа, например графические gif. jpg, png... etc Т.е. всю страничку не нужно, нужно только файлики нттп запросом, подскажите?!

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