Mostrando entradas con la etiqueta echo. Mostrar todas las entradas
Mostrando entradas con la etiqueta echo. Mostrar todas las entradas

lunes, 25 de julio de 2011

Servidor simple de echo UDP

Ya tengo listo el servidor UDP de echo, la verdad es que las herramientas que nos brindan las librerías Qt son muy potentes y fáciles de usar.

echoserver.h
#ifndef ECHOSERVER_H
#define ECHOSERVER_H

#include "IForm.h"
#include 
#include 

namespace Ui {
    class EchoServer;
}

class EchoServer : public QWidget
{
    Q_OBJECT

public:
    explicit EchoServer(QWidget *parent = 0);
    virtual ~EchoServer();
    static const quint16 PORT_MIN;
    static const quint16 PORT_MAX;
    static const quint16 PORT_DEFAULT;

protected:
    QUdpSocket *udpServer;

    virtual void putTexts();
    virtual void setuid();

    static const QString START;
    static const QString STOP;

public slots:
    void onClickStart();
    void readPendingDatagrams();

private:
    Ui::EchoServer *ui;
    bool started;

};

#endif // ECHOSERVER_H

echoserver.cpp
#include "echoserver.h"
#include "ui_echoserver.h"
#include 

const quint16 EchoServer::PORT_MIN = 1;
const quint16 EchoServer::PORT_MAX = 65535;
const quint16 EchoServer::PORT_DEFAULT = 8888;

const QString EchoServer::START = tr("Start");
const QString EchoServer::STOP = tr("Stop");

EchoServer::EchoServer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::EchoServer)
{
    ui->setupUi(this);
    this->udpServer = new QUdpSocket(this);
    this->started = false;
    putTexts();
    setuid();    
}

EchoServer::~EchoServer()
{
    delete ui;
    delete this->udpServer;
    qDebug("Delete EchoServer");
}

void EchoServer::putTexts()
{
    this->setWindowTitle(tr("Servidor echo UDP"));
    ui->lbPort->setText(tr("Port"));
    ui->pbStart->setText(tr("Start"));
}

void EchoServer::setuid()
{
    setAttribute(Qt::WA_DeleteOnClose);
    connect(ui->pbStart, SIGNAL(clicked()),SLOT(onClickStart()));
    connect(ui->sldPort, SIGNAL(valueChanged(int)), ui->lcdPort, SLOT(display(int)));

    ui->sldPort->setMinimum(EchoServer::PORT_MIN);
    ui->sldPort->setMaximum(EchoServer::PORT_MAX);
    ui->sldPort->setValue(EchoServer::PORT_DEFAULT);
}

void EchoServer::onClickStart()
{

    if(!this->started)
    {
        qDebug("Server started");
        quint16 port = ui->lcdPort->value();
        udpServer->bind(port, QUdpSocket::ShareAddress);
        connect(udpServer, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
        ui->pbStart->setText(STOP);
    } else
    {
        qDebug("Server stoped");
        udpServer->close();
        ui->pbStart->setText(START);
    }

    this->started = !this->started;
}

void EchoServer::readPendingDatagrams()
{
    qDebug("readPendingDatagrams");
    while (udpServer->hasPendingDatagrams())
    {
         QByteArray datagram;
         datagram.resize(udpServer->pendingDatagramSize());
         QHostAddress sender;
         quint16 senderPort;

         udpServer->readDatagram(datagram.data(), datagram.size(),
                                 &sender, &senderPort);

         QString str(datagram);
         str.append(" from " + sender.toString() + " on " + QDateTime::currentDateTime().toString()+ "\n");
         ui->textBrowser->insertPlainText(str);
         udpServer->writeDatagram(datagram, sender, senderPort);
     }
}

Para iniciar el servidor, simplemente hay que indicar el puerto por el que escuchará y el modo. Además hay que conectar la llegada de paquetes a una función, en este caso la función es readPendingDatagrams() y se ejecutará cada vez que llegue un paquete UDP.

quint16 port = ui->lcdPort->value();
udpServer->bind(port, QUdpSocket::ShareAddress);
connect(udpServer, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

En la función readPendingDatagrams() es donde se realiza el procesamiento de datos y se monta la respuesta para el cliente. En este caso el procesamiento de datos consiste en sacar los datos recibidos por pantalla y la respuesta contiene exactamente los mismos datos que se han recibido.

while (udpServer->hasPendingDatagrams())
{
     QByteArray datagram;
     datagram.resize(udpServer->pendingDatagramSize());
     QHostAddress sender;
     quint16 senderPort;

     udpServer->readDatagram(datagram.data(), datagram.size(),&sender, &senderPort);

     QString str(datagram);
     str.append(" from " + sender.toString() + " on " + QDateTime::currentDateTime().toString()+ "\n");
     ui->textBrowser->insertPlainText(str);
     udpServer->writeDatagram(datagram, sender, senderPort);
}

Como siempre podeis descargar el código desde el svn, para esta versión en concreto desde aquí:
svn checkout http://infobasic.googlecode.com/svn/tags/infobasic-0.0.3 infobasic-read-only

domingo, 24 de julio de 2011

Cliente simple echo. UDP. Añadida selección de puerto.

Se ha añadido al cliente echo udp, la selección de puerto, para ello se ha usado un QSlider y un QLCDNumber.

Conectamos el valor producido por el QSlider al valor mostrado en el QLCDNumber y configuramos los valore máximos y mínimos del QSlider a los valores de puerto máximo y mínimo respectivamente.

const quint16 EchoClient::PORT_MIN = 1;
const quint16 EchoClient::PORT_MAX = 65535;
const quint16 EchoClient::PORT_DEFAULT = 8888;

...

void EchoClient::setuid()
{
    setAttribute(Qt::WA_DeleteOnClose);
    connect(ui->pbSend, SIGNAL(clicked()),SLOT(onClickSend()));
    connect(ui->sldPort, SIGNAL(valueChanged(int)), ui->lcdPort, SLOT(display(int)));

    ui->sldPort->setMinimum(EchoClient::PORT_MIN);
    ui->sldPort->setMaximum(EchoClient::PORT_MAX);
    ui->sldPort->setValue(EchoClient::PORT_DEFAULT);
}

Por último en la función de enviar cogemos el valor del puerto del QLCDNumber y lo enviamos al host especificado en el QLineEdit.

void EchoClient::onClickSend()
{
    qDebug("onClickSend");

    QHostInfo info = QHostInfo::fromName(ui->leServerName->text());
    if (!info.addresses().isEmpty())
    {
        QHostAddress address = info.addresses().first();
        QByteArray ba = ui->leText->text().toLocal8Bit();
        const char *txt = ba.data();
        qint16 len = ui->leText->text().length();
        qint16 port = ui->sldPort->value();

        QUdpSocket *udp =new QUdpSocket(this);
        udp->writeDatagram(txt, len, address,  port);
        delete udp;
    } else
    {
        QMessageBox msgBox;
        msgBox.setWindowTitle(tr("Error"));
        msgBox.setText(tr("Error host not found"));
        msgBox.setIcon(QMessageBox::Critical);
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.exec();
    }
}

Para descargar esta versión:

svn checkout http://infobasic.googlecode.com/svn/tags/infobasic-0.0.2 infobasic-read-only