Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [QT] QHttp ограничение скорости закачки 
V
    Опции темы
ecspertiza
Дата 21.6.2009, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



Возможно ли используя QHttp ограничить скорость закачки как это делает DownloadMaster или любые торрент клиенты?


--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
SABROG
Дата 21.6.2009, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Управлять скоростью скачивания можно ограничивая в размерах буффер сокета и чтением из него настолько часто насколько быстрей ты хочешь что-то скачать. Если буффер полностью заполняется, то чтение данных из сокета прекращается до того момента пока в буффере не появится место, при этом данные, которые отправляет удаленный сокет никуда не деваются, он просто их не отправляет до того момента, пока скачивающий ему не скажет продолжить.

Для QHttp это можно сделать через 
int QHttp::setSocket ( QTcpSocket * socket )

но надо предварительно создать сокет и вызвать void QAbstractSocket::setReadBufferSize ( qint64 size ).

Но я рекомендую перевести приложение на QNetworkAccessManager, т.к. в Qt 4.6 класс QHttp будет deprecated. Уже сейчас тролли не принимают багрепорты на этот класс.

А для QNAM достаточно вызвать void QNetworkReply::setReadBufferSize ( qint64 size )   [virtual], который возвратится от QNetworkReply * QNetworkAccessManager::get ( const QNetworkRequest & request )

Но еще раз повторюсь. Чтобы замедлить скачивание надо игнорить сигнал readyRead так часто как тебе нужно, а значит тебе придется  проверять сколько времени прошло с момента последнего чтения данных. Т.е. если тебе нужно ограничить скорость до 500кб/с, то тут у тебя 2 варианта. Ты можешь выставить размер буффера в 500кб и проверять прошла ли секунда перед следующим чтением или ты можешь влиять через время, установить размер буффера в 50 байт и читать их каждые 100 мс.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
ecspertiza
Дата 22.6.2009, 08:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



Спасибо доходчего объяснил smile +1


--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
ecspertiza
Дата 22.6.2009, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



SABROG,  можешь глянуть правильно ли я тебя понял я накидал небольшой примерчик smile всё бы ничего но память жрёт как свиняка.
Где я мог недодумать?

Код

#include <QtCore/QCoreApplication>

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>
#include <QFile>
#include <QFileInfo>

#define USAGE QT_TRANSLATE_NOOP("threadDownload::main", "usage: %s <link>")

class ClassDownload : public QObject
{
    Q_OBJECT

    public:
        ClassDownload(QObject *parent = 0,QString link = "");

    private:
        QNetworkAccessManager manager;

        QString link;
        QString fileName;

        QList<QNetworkReply *> currentDownload;

        void saveToDisk(QString , QIODevice *);
        void replyComplite(QNetworkReply*);

    private slots:
        void replyFinished(QNetworkReply*);

    protected:
        void timerEvent(QTimerEvent *event);

};

ClassDownload::ClassDownload(QObject *parent,QString _link)
        :QObject(parent)
{
    link = _link;

    QUrl url(link);

    connect(&manager, SIGNAL(finished(QNetworkReply*)),
         this, SLOT(replyFinished(QNetworkReply*)));

    QNetworkRequest request;
    request.setUrl(url);
    request.setRawHeader("User-Agent", "DCross 1.0");
    request.setRawHeader("Referer",url.host().toLocal8Bit().data());

    QNetworkReply *reply = manager.head(request);
}

void ClassDownload::replyFinished(QNetworkReply *reply)
{
    if (reply->error())
    {
        qDebug() << "error " << reply->errorString();
        qApp->quit();
    }
    else
    {
        if (reply->operation() == QNetworkAccessManager::HeadOperation)
        {
            uint length = reply->header(QNetworkRequest::ContentLengthHeader).toUInt();
            qDebug() << "lengt file" << length;

            QFileInfo fileInfo = QUrl(link).path();
            fileName = fileInfo.fileName();

            QNetworkRequest request;
            request.setUrl(QUrl(link));

            QNetworkReply *reply = manager.get(request);
            reply->setReadBufferSize(1048576);
            currentDownload.append(reply);
            qDebug() << "get file";

            startTimer(1000);
        }
    }
}

void ClassDownload::saveToDisk(QString fileName, QIODevice *data)
{
    QFile *file = new QFile(fileName);
        file->open(QIODevice::Append);
        file->write(data->readAll());
        file->close();
}


void ClassDownload::timerEvent(QTimerEvent *event)
{
    if (currentDownload.count() == 0)
    {
        qDebug() << "download complite";
        qApp->quit();
    }

    for (int i = 0;i<currentDownload.count();i++)
    {
        if (currentDownload[i]->size() != 0)
        {
            qDebug() << currentDownload[i]->size();
            saveToDisk(fileName,currentDownload[i]);
            qDebug() << currentDownload[i]->size();
        }else
        {
            replyComplite(currentDownload[i]);
        }
    }
}

void ClassDownload::replyComplite(QNetworkReply *reply)
{
    currentDownload.removeAll(reply);
    reply->deleteLater();
}

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        qDebug(USAGE, argv[0]);
        return 0;
    }

    QCoreApplication a(argc, argv);

    ClassDownload *dwn = new ClassDownload(0,argv[1]);

    return a.exec();
}

#include "main.moc"




--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
SABROG
Дата 22.6.2009, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Ты бы хоть объяснил, что этот код делает, а то я ничего не понял smile

Тут утечка у тебя похоже, указатель на QFile не удаляется:

Код

    QFile *file = new QFile(fileName);
        file->open(QIODevice::Append);
        file->write(data->readAll());
        file->close();


Да и код по меньшей мере странный. У тебя этот метод вызывается так часто насколько большой размер у файла и насколько маленький буффер. При быстрых скоростях это утопия, если надо записать скажем 50 байт в файл, открытие и закрытие файла, постоянно файловые операции.

Насчет очереди не понятно - QList<QNetworkReply *> currentDownload;
Вроде запрашивается всего один Url, а для чего целый список, как у тебя может прийти скажем десяток replyFinished? Да и по логике получается, что в один и тот же файл записываются данные с каждого запроса в этом списке.

Этот код мне тоже не совсем понятен. Через метод size() идет попытка определить есть ли доступные данные для считывания и если нет, то мы зачем-то обрубаем всё нафиг, типа тормозишь сервак или провайдер ну и х. с тобой, не буду я докачивать ничего, даже если ты ответишь мне через 20 секунд.
Код

    for (int i = 0;i<currentDownload.count();i++)
    {
        if (currentDownload[i]->size() != 0)
        {
            qDebug() << currentDownload[i]->size();
            saveToDisk(fileName,currentDownload[i]);
            qDebug() << currentDownload[i]->size();
        }else
        {
            replyComplite(currentDownload[i]);
        }
    }


Метод replyComplite (почему не complete?). removeAll можно заменить на removeOne(reply), сомневаюсь, что там может быть несколько идентичных указателей, а выйгрыш в скорости будет, т.к. проход по массиву закончится при первом совпадении.

Вообще идея с таймером странная какая-то. Может быть запускать таймер в слоте на сигнал readyRead, который прочитает нужные нам данные из буффера с некоторой паузой?

Насчет утечек памяти, попробуй использовать IBM Rational Purify, чтобы найти места, где утекает память.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
ecspertiza
Дата 22.6.2009, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



Цитата(SABROG @  22.6.2009,  13:44 Найти цитируемый пост)
Ты бы хоть объяснил, что этот код делает, а то я ничего не понял 


Извеняюсь торопился smile

насчёт записи в файл согласен затупил.


Цитата(SABROG @  22.6.2009,  13:44 Найти цитируемый пост)
Насчет очереди не понятно - QList<QNetworkReply *> currentDownload;


Я хочу сделать закачку в несколько потоков, и думал что QList<QNetworkReply *> мне в этом поможет, ан нет это просто очередь smile

Мне нужно сделать многопоточную закачку с ограниченой скоростью, но вот когда я в отдельном потоке создаю QNetworkAccessManager софтина начинает ругаться вот так

Код

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x80d0d38), parent's thread is QThread(0x8050328), current thread is Thread(0x80d0d30)


собственно вот код

Код

#include <QtCore/QCoreApplication>

#include "QThread"
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>
#include <QFile>
#include <QFileInfo>

#define USAGE QT_TRANSLATE_NOOP("threadDownload::main", "usage: %s <link> <count thread>")

class Thread :public QThread //Поток для закачивания фрагмента
{
    Q_OBJECT

    public:
        Thread(QObject *parent = 0,QString link = "",QString fileName = "",uint begin = 0,uint end = 0);

    protected:
        void run();

    private:
        QNetworkAccessManager *manager;//Нетворк менеджер
        QNetworkReply *reply;
        QString link; // Сылка
        QString fileName; // имя файла для записи
        uint begin; // Начало скачавания\начало записи в файл
        uint end; // До куда скачивать

        QFile file; // Файл для записи

        void writeToFile();

    private slots:
        void replyFinished(QNetworkReply*);
        void readyReal();
};

Thread::Thread(QObject *parent,QString _link,QString _fileName,uint _begin,uint _end)
        :QThread(parent)
{
    manager = new QNetworkAccessManager(0);

    connect(manager, SIGNAL(finished(QNetworkReply*)),
         this, SLOT(replyFinished(QNetworkReply*)));

    begin = _begin;
    end = _end;
    link = _link;
    fileName = _fileName;

    file.setFileName(fileName); // Задаём имя файла

        if (!file.open(QIODevice::WriteOnly)) // открываем файл
        {
            qDebug() << "file error open" << file.errorString();
            terminate();
        }
}


void Thread::run()
{
    QString byte;
    QString num;

    byte+= "bytes=";
    byte+= num.setNum(begin);
    byte+= "-";
    byte+=num.setNum(end);

    QNetworkRequest request;  // Формируем запрос
    request.setUrl(QUrl(link));
    request.setRawHeader("Range",byte.toLocal8Bit().data()); // задаём размер фрагмента

    reply = manager->get(request); //Отправляем запрос
    reply->setReadBufferSize(500); //Устанавливаем буфер
    connect(reply,SIGNAL(readyRead()),this,SLOT(readyReal()));

}

void Thread::replyFinished(QNetworkReply*)
{
    writeToFile();
}

void Thread::readyReal()
{
    writeToFile();
}

void Thread::writeToFile()
{
    file.seek(begin); // Устанавливаем точку записи
    begin += reply->size();
    file.write(reply->readAll()); // пишем
}

class ClassDownload : public QObject // Класс для получения информации о файле(длинны), и создания потоков
{
    Q_OBJECT

    public:
        ClassDownload(QObject *parent,QString link = "",int count_thread = 1);

    private:
        QNetworkAccessManager manager;

        QString link; //Сылка
        QString fileName; //Имя файла
        int count_thread;//Количество потоков
        QFile file;

        uint length;//Длина файла

    private slots:
        void replyFinished(QNetworkReply*);
};

ClassDownload::ClassDownload(QObject *parent,QString _link,int _count_thread)
:QObject(parent)
{
    connect(&manager, SIGNAL(finished(QNetworkReply*)),
         this, SLOT(replyFinished(QNetworkReply*)));

    link = _link;
    count_thread = _count_thread;
    QUrl url(link);

    QNetworkRequest request; //Формируем заголовок
    request.setUrl(url);
    request.setRawHeader("User-Agent", "DCross 1.0");
    request.setRawHeader("Referer",url.host().toLocal8Bit().data());

    QNetworkReply *reply = manager.head(request);// Отправляем

}

void ClassDownload::replyFinished(QNetworkReply *reply)
{
    if (reply->error())
    {
        qDebug() << "error " << reply->errorString();
        qApp->quit();
    }
    else
    {
        if (reply->operation() == QNetworkAccessManager::HeadOperation)
        {

            reply->deleteLater();
            length = reply->header(QNetworkRequest::ContentLengthHeader).toUInt(); // Получаем длинну файла
            qDebug() << "lengt file" << length;

            QFileInfo fileInfo = QUrl(link).path();
            fileName = fileInfo.fileName(); // Получаем имя файла

            file.setFileName(fileName);
            file.open(QIODevice::WriteOnly);
                file.resize(length); // Задаём размер файла

            for (int i = 0;i<count_thread;i++) // Создаём потоки
            {
                uint begin = (length/count_thread)*i;
                uint end = (length/count_thread)*(i+1);

                    Thread *th = new Thread(0,link,fileName,begin,end);
                    th->start();
            }

            file.close();
        }
    }
}

int main(int argc, char *argv[])
{

    if (argc < 3)
    {
        qDebug(USAGE, argv[0]);
        return 0;
    }

    QCoreApplication a(argc, argv);

    QString num = argv[2];

    ClassDownload *dwn = new ClassDownload(0,argv[1],num.toInt());

    return a.exec();
}

#include "main.moc"




--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
SABROG
Дата 22.6.2009, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



smile ну блин, давай вспоминать тему потоков. Объекты созданные в конструкторе QThread - принадлежат главному потоку, объекты созданные в run() - новому потоку. Метод QObject::moveToThread помогает переместить объект в нужный поток, но не позволяет его вернуть обратно, при этом у объекта не должно быть родителя.

Я бы посоветовал посмотреть в сторону QtConcurrent вместо QThread, и использовать QFuture для сборки файла из многопоточной закачки.

Это сообщение отредактировал(а) SABROG - 22.6.2009, 16:42


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
ecspertiza
Дата 23.6.2009, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



У меня такое ощущение что QNetworkAccessManager может работать только в главном потоке, я накидал пример в котором создаётся поток и внём я пытаюсь получить http заголовок чтобы определить размер файла, всё замечательно никаких ошибок но и заголовки при этом не передаются smile вот примерчик



Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  threadDownload5.tar 10,00 Kb


--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
ecspertiza
Дата 23.6.2009, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



всё разобрался прошу прощения за панику smile
SABROG, отдельное спасибо оченно помог.


--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
ecspertiza
Дата 25.6.2009, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



Что то я совсем запутолся, есть софтина у неё есть класс закачки, он должен отправить заголовок получить размер файла и создать нужное количество потоков для скачивания кусками, если я в потоке задаю размер буффера то  софтина жудко жрёт память, если не задаю вылетает.

она в аттаче. не исключаю возможность кривых рук, ткните носом где косячу, а то два дня ковыряюсь и всё не в ту сторону.

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

Да и файл размеров 2Гб.

И вообще QNetwork* нерадует, стандартный example download, на этих компанентах тоже жрёт память, при скачивании большого файла тоже вылетает. Что это? Косяк разработчика?

Это сообщение отредактировал(а) ecspertiza - 25.6.2009, 11:52

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  threadDownload4.tar 570,00 Kb


--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
SABROG
Дата 25.6.2009, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



 smile 

Код

lengt file 1739587584
0 173958758 "http://server/test.iso" "c:\/test.iso"
173958758 347917516 "http://server/test.iso" "c:\/test.iso"
QObject::startTimer: timers cannot be started from another thread
QObject::startTimer: timers cannot be started from another thread
347917516 521876274 "http://server/test.iso" "c:\/test.iso"
521876274 695835032 "http://server/test.iso" "c:\/test.iso"
695835032 869793790 "http://server/test.iso" "c:\/test.iso"
QObject::startTimer: timers cannot be started from another thread
QObject::startTimer: timers cannot be started from another thread
869793790 1043752548 "http://server/test.iso" "c:\/test.iso"

QObject::startTimer: timers cannot be started from another thread
1043752548 1217711306 "http://server/test.iso" "c:\/test.iso"

QObject::startTimer: timers cannot be started from another thread
1217711306 1391670064 "http://server/test.iso" "c:\/test.iso"

1391670064 1565628822 "http://server/test.iso" "c:\/test.iso"

QObject::startTimer: timers cannot be started from another thread
QObject::startTimer: timers cannot be started from another thread
1565628822 1739587580 "http://server/test.iso" "c:\/test.iso"

QObject::startTimer: timers cannot be started from another thread
QObject::startTimer: timers cannot be started from another thread


QWaitCondition: Destroyed while threads are still waiting


У тебя тут заккоментировано:

Код

//reply->setReadBufferSize(10485760);


И я не нашел метода, который бы писал в файл на сигнал readyRead. Ты пишешь в файл здесь:

Код

void Thread::writeToFile()
{
    qDebug() << "write begin" << begin << "reply size = "<<reply->size();;
    file->seek(begin);
    begin += reply->size();
    file->write(reply->readAll()); // пишем
}


В документации сказано, если ты не ловишь событие readyRead, то файл выкачается полностью. Потому наверно и память жрется.
Я расскомментировал setReadBufferSize и все-равно не понял почему выкачивание не останавливается при полном заполнении буффера.
Цитата

QNetworkReply will try to stop reading from the network once this buffer is full


Если 10 потоков по 10 мегабайт в буффере, то прога должна кушать около 100Мб оперативки, а жрет 800 мегов и потом падает.


Это сообщение отредактировал(а) SABROG - 25.6.2009, 13:39


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
ecspertiza
Дата 25.6.2009, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



Забавно у меня пока такого небыло smile


--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
ecspertiza
Дата 25.6.2009, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



Ошибка возникает при чтении из QNetworkReply вот в этом месте

Код

    file->write(reply->readAll(),sizeof(reply->readAll())); // пишем


Причём если всё это делать не в потоке то всё нормально и память освобождается после reply->readAll() и закачка идёт нормально, а если в потоке то читает некоторое время а потом отваливается, може из за того что QNetworkReply создаётся не в потоке, но переместить его туда методом moveToThread тоже не получается возникает ошибка сигментирования, вообщем я совсем запутолся.


--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
SABROG
Дата 25.6.2009, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(ecspertiza @  25.6.2009,  13:58 Найти цитируемый пост)
file->write(reply->readAll(),sizeof(reply->readAll())); // пишем


На самом деле очень странная запись. 2 раза читать через readAll не надо, ведь после первого readAll буффер очищается. К тому же write() сам знает какой размер у QByteArray.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
ecspertiza
Дата 25.6.2009, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 763
Регистрация: 3.11.2008
Где: г.Смоленск

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



ну это я просто привёл кусок кода как в проге в случае с file->write(reply->readAll()) всё тоже самое.


--------------------
С уважением,
мастер конфетного цеха!

онлайн компилер
залип
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




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


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

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