crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> Qt4 TCP-сервер 150 kbit/s
Eugene K
  опции профиля:
сообщение 14.5.2019, 20:35
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 2
Регистрация: 14.5.2019
Пользователь №: 5103

Спасибо сказали: 0 раз(а)




Репутация:   0  



Здравствуйте. У меня есть TCP-сервер на одной машине и TCP-клиент на другой машине.
Клиент подключается к серверу и передает ему пакеты данных.
Количество пакетов 40000+.
Длина пакетов до 400 байт.
При выдаче пакетов с периодом 50 мс есть потери пакетов на сервере.
При выдаче пакетов с периодом 200 мс потерь пакетов на сервере очень редкие.
Программа написана на Qt4.


Вопросы:

1. Нужна скорость передачи и приема 150 kbit/s без потерь пакетов.
Что доделать в программе?

2. Нужно ли для этого увеличивать частоту выдачи или надо увеличивать объем
передаваемых данных?

3. Надо ли использовать QDataStream для передачи данных?

4. Как возможно увеличить скорость передачи-приема до 1 Mbit/s.

5. Как измерить скорость передачи-приема в Kbit/s?


Текст сервера:

#define READ_BUF_SIZE  10000
char buf_c[8000000];


//конструктор
{
//TCP-сервер
    clientConnection = new QTcpSocket(this);  
    tcpServer = new QTcpServer();
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnect()));
    
            
    connect(wdgComm, SIGNAL(tcp_init()), SLOT(tcp_init()));    
}


void frmMain::tcp_init()
{
    if (tcpServer->isListening())
    {
    tcpServer->close();
    }

    if (!tcpServer->listen(QHostAddress::Any, wdgComm->spbHostPort->value()))
    {
        //TCP-серверу не удалось запуститься
        return;
    }
}


void frmMain::newConnect()
{
    clientConnection = tcpServer->nextPendingConnection();    
    
    connect(clientConnection, SIGNAL(readyRead()),
            this, SLOT(receivePkg()));  

    connect(clientConnection, SIGNAL(disconnected()),
            clientConnection, SLOT(deleteLater()));          
}



void frmMain::receivePkg()
{
    if(listSt.at(0).toInt()==21)    
    s_t();
}



void frmMain::s_t()
{    
  
    read_size = clientConnection->read(buf_c, READ_BUF_SIZE);
}


Текст клиента:

//класс главного окна
//конструктор
{
   t = new QTimer(this);
   t->setSingleShot(false);
   t->setInterval(50); // период выдачи, мс
   connect(t, SIGNAL(timeout()), SLOT(write2()));

   //net
   wdgComm = new frmComm(this);    
   connect(pushButton_2, SIGNAL(clicked()), wdgComm, SLOT(show()));//
   port = wdgComm->port();
}


int frmMain::write2()
{
    QByteArray pkg;

    for(j=0; j<mas_t_size[kol_send]; j++)    
    {
      pkg[j]=mas_t[kol_send][j];
    }

    port->write(pkg);

}


//класс окна настройки адреса и порта
class frmComm : public QWidget, public Ui::wdgComm
{
    Q_OBJECT

public :
    frmComm(QWidget * parent = 0);
    commDevice * port(void) { return com_port; }

public slots :
    void reset(void);

private :
    QSettings * settings;
    commDevice * com_port;
};


//конструктор окна настройки
frmComm::frmComm(QWidget * parent) : QWidget(parent, Qt::Window)
{
    connect(btnSet, SIGNAL(clicked()), SLOT(reset()));

    settings = new QSettings("comm.ini", QSettings::IniFormat, this);

    ledHostAddress->setText(settings->value("host_address", "192.168.0.100").toString());
    spbHostPort->setValue(settings->value("host_port", 5200).toInt());
    com_port = new commDevice(this);
    return;
}


void frmComm::reset(void)
{
    settings->setValue("host_address", ledHostAddress->text());
    settings->setValue("host_port", spbHostPort->value());

    com_port->close();
    com_port->connectToHost(ledHostAddress->text(), spbHostPort->value());
    return;
}



//класс клиента
commDevice::commDevice(QObject * parent) : QObject(parent)
{
    comm_state = commDevice::Disconnect;
    close_flag = FALSE;

    socket = new QTcpSocket(this);
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError)));
    connect(socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
    connect(socket, SIGNAL(readyRead()), SLOT(readDevice()));

    socket_reconnect_timer = new QTimer(this);
    socket_reconnect_timer->setSingleShot(TRUE);
    socket_reconnect_timer->setInterval(10000); // период переподключения сокета, мс

    return;
}


void commDevice::connectToHost(const QString & hostName, quint16 port)
{
    close_flag = FALSE;
    host_name = hostName;
    host_port = port;
    reconnectToHost();
    return;
}


void commDevice::reconnectToHost(void)
{
    socket->connectToHost(host_name, host_port);
    if(socket->waitForConnected(10000))
    {
        comm_state = commDevice::TCPSocket;
        //(tr("Выполнено подключение к TCP-серверу\n", ""), Qt::black);
    }
    return;
}


void commDevice::socketDisconnected(void)
{
    comm_state = commDevice::Disconnect;
    if(!close_flag)
        socket_reconnect_timer->start();
    return;
}


void commDevice::socketError(QAbstractSocket::SocketError err)
{
    switch(err)
    {
    case QAbstractSocket::ConnectionRefusedError :
        //(tr("Соединение не выполнено", "The connection was refused by the peer (or timed out)."), Qt::red);
        break;
    case QAbstractSocket::RemoteHostClosedError :
        //(tr("Удаленный сервер закрыл соединение", "The remote host closed the connection."), Qt::red);
        break;
    case QAbstractSocket::HostNotFoundError :
        //(tr("Удаленный сервер не найден", "The host address was not found."), Qt::red);
        break;
    default :
        //(tr("Ошибка сокета ") + QString::number(err), Qt::red);
    }
    socket->abort();
    comm_state = commDevice::Disconnect;
    socket_reconnect_timer->start();
    return;
}


//функция выдачи пакета
int commDevice::write(const QByteArray & pkg)
{
    DWORD charsWritten = 0;
    int written = 0;
    bool ok;

    written = socket->write(pkg, pkg.size());

    return written;
}

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
Алексей1153
  опции профиля:
сообщение 15.5.2019, 7:18
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2889
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Eugene K, чтобы пакеты не "терялись", нужно не скорость или размер пакетов менять, а увеличивать размер буфера на приёмной стороне - скорее всего, это именно получатель не успевает их пережёвывать. Желательно максимально быстро вычитывать из сокета и складывать в свой буфер для обработки. Лично я делаю работу с сокетами в отдельном потоке без использования сигналов и слотов, так структура наиболее упрощённая и наглядная. Сам поток занимается только вычиткой, а обработка делается другим потоком

в твой код-рассыпуху я не вникал, уж извини. Но настораживает:
- наличие new при отсутствии явных delete (не надо про то, что Qt это иногда позволяет. Лучше не злоупотреблять, если это не виджеты или элементы таблиц)
- наличие статического массива

Сообщение отредактировал Алексей1153 - 15.5.2019, 7:22
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 16.11.2019, 1:48