QT中的 TCP 通信 (一)

</pre><p>客户端 :</p><p>widget.h</p><p style="TEXT-INDENT: 0px; MARGIN: 0px; -qt-paragraph-type: empty; -qt-block-indent: 0"></p><pre style="TEXT-INDENT: 0px; MARGIN: 0px; -qt-block-indent: 0"><span style="color:#000080;">#ifndef</span><span style="color:#c0c0c0;"> </span>WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QtNetwork>
/* 4.5 版本的 QT 头文件 - ARM 开发板使用的 Qt 版本
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QTcpServer>
*/
#include <QLineEdit>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QFile>
#include <QFileDialog>
#include <QString>
#include <QByteArray>
#include <QSlider>
#include <QSpinBox>
 
namespace Ui
{
    class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
private :
    QLineEdit *hostLineEdit;  /* 服务器 IP 编辑框 */
    QLineEdit *portLineEdit;  /* 服务器端口编辑框 */
 
    QLabel *ipLabel;
    QLabel *portLabel;
    QLabel *bright;
 
    QPushButton *connectButn;
    QPushButton *cancleButn;
 
    QLabel      *tempLabel;
    QSpinBox    *tempSpinBox;
    QPushButton *tempFreshButn;
    QPushButton *tempSetButn;
 
    QLabel      *wetLabel;
    QSpinBox    *wetSpinBox;
    QPushButton *wetFreshButn;
    QPushButton *wetSetButn;
 
    QPushButton *bedLightBtn;     /*  */
    QLabel      *bedLightLabel;
    QPushButton *mainLightBtn;
    QLabel      *mainLightLabel;
    QPushButton *kitchLightBtn;
    QLabel      *kitchLightLabel;
 
    QSpinBox    *spinbox;
    QSlider     *slider;
 
    QHBoxLayout *hbox1;
    QHBoxLayout *hbox2;
    QHBoxLayout *hbox3;
    QHBoxLayout *hbox4;
    QHBoxLayout *hbox5;
    QGridLayout *grid;
    QVBoxLayout *vbox;
 
    QTcpSocket  *tcpClient;
 
    bool bedBool;
    bool mainBool;
    bool kitchBool;
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
private slots :
    void hostEdit(const QString &);
    void clickOK();
    void clickCancl();
    void sendData(int value);
    void serverConnect();
    void readData();
    void bedclick();
    void mainclick();
    void kitchclick();
 
private:
    Ui::Widget *ui;
};
 
#endif // WIDGET_H
 
widget.cpp
 

#include "widget.h"
#include "ui_widget.h"
#include <QTextCodec>
#include <QMessageBox>
#include <QDataStream>
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    /* 支持中文显示 */
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
    /* 创建 socket */
    tcpClient = new QTcpSocket(this);
    /* 如果连接成功, 触发 serverConnect 函数 */
    connect(tcpClient, SIGNAL(connected()), this, SLOT(serverConnect()));
    connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readData()));
    /* 连接按键 */
    connectButn  = new QPushButton(tr("连接"));
    connectButn->setEnabled(false);
    /* 取消按键 */
    cancleButn   = new QPushButton(tr("取消"));
    cancleButn->setEnabled(false);
    ipLabel      = new QLabel(tr("服务器"));
    hostLineEdit = new QLineEdit;
    portLabel    = new QLabel(tr("端口号"));
    portLineEdit = new QLineEdit;
    tempLabel     = new QLabel(tr("温  度"));
    tempSpinBox   = new QSpinBox;
    tempSpinBox->setRange(-20, 50);
    tempFreshButn = new QPushButton(tr("刷新"));
    tempSetButn   = new QPushButton(tr("设置"));
    wetLabel     = new QLabel(tr("湿  度"));
    wetSpinBox   = new QSpinBox;
    wetSpinBox->setRange(0, 100);
    wetFreshButn = new QPushButton(tr("刷新"));;
    wetSetButn   = new QPushButton(tr("设置"));
    bright  = new QLabel(tr("亮  度"));
    spinbox = new QSpinBox;
    slider  = new QSlider(Qt::Horizontal);
    spinbox->setRange(0, 100);
    spinbox->setValue(50);
    slider->setRange(1, 100);
    slider->setValue(50);
    bedLightBtn   = new QPushButton(tr("打 开"));
    bedLightLabel = new QLabel(tr("   bedroom"));
    bedBool = false;
    mainLightBtn   = new QPushButton(tr("打 开"));
    mainLightLabel = new QLabel(tr("    main"));
    mainBool = false;
    kitchLightBtn   = new QPushButton(tr("打 开"));
    kitchLightLabel = new QLabel(tr("    kitch"));
    kitchBool = false;
    connect(slider,  SIGNAL(valueChanged(int)), this,    SLOT(sendData(int)));
    connect(slider,  SIGNAL(valueChanged(int)), spinbox, SLOT(setValue(int)));
    connect(spinbox, SIGNAL(valueChanged(int)), slider,  SLOT(setValue(int)));
    /* IP 编辑框和端口编辑框, 触发的槽函数 */
    connect(hostLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(hostEdit(const QString &)));
    connect(portLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(hostEdit(const QString &)));
    /* 连接按钮与取消按钮连接的槽函数 */
    connect(connectButn,  SIGNAL(clicked()), this, SLOT(clickOK()));
    connect(cancleButn,   SIGNAL(clicked()), this, SLOT(clickCancl()));
    connect(bedLightBtn,  SIGNAL(clicked()), this, SLOT(bedclick()));
    connect(mainLightBtn, SIGNAL(clicked()), this, SLOT(mainclick()));
    connect(kitchLightBtn,SIGNAL(clicked()), this, SLOT(kitchclick()));
    /*----------------------- 控件布局 -------------------------*/
    hbox1 = new QHBoxLayout;
    hbox1->addWidget(ipLabel);
    hbox1->addWidget(hostLineEdit);
    hbox1->addWidget(connectButn);
    hbox2 = new QHBoxLayout;
    hbox2->addWidget(portLabel);
    hbox2->addWidget(portLineEdit);
    hbox2->addWidget(cancleButn);
    hbox3 = new QHBoxLayout;
    hbox3->addWidget(tempLabel);
    hbox3->addWidget(tempSpinBox);
    hbox3->addWidget(tempFreshButn);
    hbox3->addWidget(tempSetButn);
    hbox4 = new QHBoxLayout;
    hbox4->addWidget(wetLabel);
    hbox4->addWidget(wetSpinBox);
    hbox4->addWidget(wetFreshButn);
    hbox4->addWidget(wetSetButn);
    hbox5 = new QHBoxLayout;
    hbox5->addWidget(bright);
    hbox5->addWidget(slider);
    hbox5->addWidget(spinbox);
    grid = new QGridLayout;
    grid->addWidget(bedLightBtn,    0, 0);
    grid->addWidget(mainLightBtn,   0, 1);
    grid->addWidget(kitchLightBtn,  0, 2);
    grid->addWidget(bedLightLabel,  1, 0);
    grid->addWidget(mainLightLabel, 1, 1);
    grid->addWidget(kitchLightLabel,1, 2);
    vbox = new QVBoxLayout;
    vbox->addLayout(hbox1);
    vbox->addLayout(hbox2);
    vbox->addLayout(hbox3);
    vbox->addLayout(hbox4);
    vbox->addLayout(hbox5);
    vbox->addLayout(grid);
    setLayout(vbox);
    QWidget::setMaximumWidth(268);
    /* 设置固定高度, sizeHint 返回的是最合适的大小 */
    QWidget::setFixedHeight(sizeHint().height());
    /* 设置固定宽度, sizeHint 返回的是最合适的大小 */
    //QWidget::setFixedWidth(sizeHint().width());
    ui->setupUi(this);
}
/* IP 编辑框和端口编辑框槽函数 */
void Widget::hostEdit(const QString &str)
{
    /* 只有当用户输入了 IP 端口, 连接按键才可以使用 */
    if ( hostLineEdit->text().isEmpty() || portLineEdit->text().isEmpty() )
    {
       connectButn->setEnabled(false);
    }
    else
    {
       connectButn->setEnabled(true);
    }
}
/* 连接按键槽函数 */
void Widget::clickOK()
{
    /* 点击连接之后, 按键处于不可用状态 */
    connectButn->setEnabled(false);
    /* 不可修改服务器 IP 地址 */
    hostLineEdit->setEnabled(false);
    /* 不可修改服务器端口 */
    portLineEdit->setEnabled(false);
    /* 取消按钮可用 */
    cancleButn->setEnabled(true);
    /* 连接服务器 */
    tcpClient->connectToHost(hostLineEdit->text(), portLineEdit->text().toInt());
}
/* 取消按钮 */
void Widget::clickCancl()
{
    /* 连接按钮可用 */
    connectButn->setEnabled(true);
    /* IP 编辑框可用 */
    hostLineEdit->setEnabled(true);
    /* 服务器端口编辑框可用 */
    portLineEdit->setEnabled(true);
    /* 取消按钮不可用 */
    cancleButn->setEnabled(false);
    tcpClient->close();
    QMessageBox::about(NULL, "消息来自客户端", "断开服务器连接");
}
void Widget::serverConnect()
{
    if ( tcpClient->state() == QAbstractSocket::ConnectedState )
    {
        QMessageBox::about(NULL, "消息来自客户端", "连接服务器成功");
    }
}
Widget::~Widget()
{
    tcpClient->deleteLater();
    if (tcpClient != NULL)
    {
        delete tcpClient;
        tcpClient = NULL;
    }
    delete ui;
}
void Widget::sendData(int value)
{
    QByteArray  block;
    QDataStream out(&block, QIODevice::WriteOnly);
    //out.setVersion(QDataStream::Qt_4_7);
    out.setVersion(QDataStream::Qt_4_5);   /* 开发板使用的版本 */
    out << (quint16)0 << value;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));
    tcpClient->write(block);
}
void Widget::readData()
{
}
void Widget::bedclick()
{
    if ( bedBool )
    {
        bedLightBtn->setText(tr("打 开"));
        bedBool = false;
    }
    else
    {
        bedLightBtn->setText(tr("关 闭"));
        bedBool = true;
    }
}
void Widget::mainclick()
{
    if ( mainBool )
    {
        mainLightBtn->setText(tr("打 开"));
        mainBool = false;
    }
    else
    {
        mainLightBtn->setText(tr("关 闭"));
        mainBool = true;
    }
}
void Widget::kitchclick()
{
    if ( kitchBool )
    {
        kitchLightBtn->setText(tr("打 开"));
        kitchBool = false;
    }
    else
    {
        kitchLightBtn->setText(tr("关 闭"));
        kitchBool = true;
    }
}
 
 
 
服务端
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtNetWork>
/*  4.5 版本的 QT 头文件 - ARM 开发板使用的 Qt 版本
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QTcpServer>
*/
#include <QFile>
#include <QFileDialog>
#include <QString>
#include <QByteArray>
#include <QLabel>
#include <QSpinBox>
#include <QHBoxLayout>
namespace Ui
{
    class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT
private :
    QTcpServer *tcpServer;
    QTcpSocket *clientSocket;
    QLabel *bright;
    QSpinBox *spinbox;
    QHBoxLayout *hbox;
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private:
    Ui::Widget *ui;
private slots :
    void newConnect();
    void readMsg();
};
#endif // WIDGET_H
 
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QTextCodec>
#include <QDataStream>
#include <QHBoxLayout>
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    /* 支持中文显示 */
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
    bright = new QLabel(tr("亮度值"));
    spinbox = new QSpinBox;
    spinbox->setRange(0, 100);
    spinbox->setValue(0);
    hbox = new QHBoxLayout;
    hbox->addWidget(bright);
    hbox->addWidget(spinbox);
    setLayout(hbox);
    /* 设置固定高度, sizeHint 返回的是最合适的大小 */
    QWidget::setFixedHeight(sizeHint().height());
    /* 设置固定宽度, sizeHint 返回的是最合适的大小 */
    QWidget::setFixedWidth(sizeHint().width());
    tcpServer = new QTcpServer(this);
    if ( !tcpServer->listen(QHostAddress::Any, 6666) )
    {
        QMessageBox::about(NULL, "监听失败", tcpServer->errorString());
        close();
    }
    /* 有客户端连接, 发送信号触发槽函数 */
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnect()));
    ui->setupUi(this);
}
Widget::~Widget()
{
    delete tcpServer;
    delete ui;
}
/* 有客户端连接时 */
void Widget::newConnect()
{
    QMessageBox::about(NULL, "服务器消息", "有新的客户端连接");
    /* 获取建立连接的套接字 */
    clientSocket = tcpServer->nextPendingConnection();
    connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readMsg()));
    /* 关联槽函数, 当断开连接时, 会自动删除该套接字 */
    connect(clientSocket, SIGNAL(disconnected()), clientSocket, SLOT(deleteLater()));
}
void Widget::readMsg()
{
    int data;
    QDataStream in(clientSocket);
    in.setVersion(QDataStream::Qt_4_7);
    quint16 blockSize = 0;
    if ( blockSize == 0 )
    {
        if ( clientSocket->bytesAvailable() < (int)sizeof(quint16) )
        {
            return;
        }
        in >> blockSize;
    }
    in >> data;
    spinbox->setValue(data);
}
 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值