zoukankan      html  css  js  c++  java
  • 4412开发板Qt网络编程-TCP实现服务器和客户端

    网络编程有 TCP 和 UDP,TCP 编程需要用到俩个类:QTcpServer 和 QTcpSocket。

    1 TCP 实现服务器和客户端
    TCP 协议(Transmission Control Protocol)是一种面向连接的,可靠的,基于字节流的传输层通信协议,传输数据稳定可靠。
    在 help 索引中搜索到如图 两个重要类:

    服务器编程中两个类都会用到,客户端编程中只会用到 QTcpSocket 对象。
    本实验中对 QTcpServer 类的基本使用:
    (1)监听客户端连接。
    (2)每当有新的客户端连接服务器的时候,会自动触发信号,
    (3)根据当前连接上的新的客户端创建一个 Socket 对象,将数据的收发动作交给 socket 套 接字去处理。
    (4)关闭服务器 close();
    对 QTcpSocket 类的基本使用:
    (1)服务器端:有新连接时获取连接状态,绑定 socket 。
    (2)客户端:通过 socket 连接服务器,连接成功触发信号。

    (3)当有数据到来时会触发信号,用 readAll()读取。
    (4)通过读写 socket 收发数据。
    具体步骤:
    步骤一:创建工程,在工程文件.pro 中添加 network,如图:

    步骤二:设计 ui 界面,
    1. 在属性编辑栏设置主窗口大小:

    2. 添加组件
    接收窗口: Plain Text Edit
    发送窗口,IP 地址窗口,端口号窗口:Line Edit
    打开服务器,关闭服务器:Push Button
    拖拽完成后逐个布局,根据需要设置组件大小,这里端口号框设置成了最小 200

    按钮布局:拖拽按钮和弹簧,然后点击水平布局。

    然后选中全部组件,点击栅格布局:

    最后更改组件名称注释,完成后如图 :

     

    步骤三:服务器端编程:
    1.创建 QTcpServer 对象
    2.创建监听端口,使得客户端可以使用这个端口访问服务器,使用 listen 函数。
    bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
    第一个参数是绑定指定的地址(即本机服务器 IP),第二个参数是绑定的本服务器端口号。
    监听某个端口时,如果有新连接进来就发出 newConnection()信号。
    3.当服务器对象被访问时,会发出 newConnection()信号,所以为该信号添加槽函数并用一个 QTcpSocket
    对象接受客户端的访问。
    4.当socket接受缓冲区有新数据到来时,会发出readyRead()信号,为该信号添加槽函数,使用readyRead()
    读取。
    5.socket 发送数据可直接调用 write()成员函数。
    6.关闭端口号。
    代码如下:

    #include <QMainWindow>
    #include <QTcpServer>
    #include <QTcpSocket>
    namespace Ui {
    class TcpServer;
    }
    class TcpServer : public QMainWindow
    {
    Q_OBJECT
    public:

    explicit TcpServer(QWidget *parent = 0); ~TcpServer();
    QTcpServer * tcpServer;
    QTcpSocket * tcpSocket;
    public slots:
    void newConnection_Slot(void);
    void readyRead_Solt(void);
    private slots:
    void on_openBu_clicked();
    void on_sendBu_clicked();
    void on_closeBu_clicked();
    private:
    Ui::TcpServer *ui;
    };
    #include "tcpserver.h" #include "ui_tcpserver.h" #include <QTcpServer>
    #include <QTcpSocket>
    #include <QString>
    TcpServer::TcpServer(QWidget *parent) :
    QMainWindow(parent), ui(new Ui::TcpServer)
    {
    ui->setupUi(this);
    tcpServer = new QTcpServer(this);
    tcpSocket = new QTcpSocket(this);
    //连接信号与槽函数进行绑定
    connect(tcpServer,SIGNAL(newConnection()),SLOT(newConnection_Slot()));
    }
    //连接信号槽函数

    void TcpServer::newConnection_Slot(void)
    {
    //连接客户端后 socket
    tcpSocket = tcpServer->nextPendingConnection();
    //套接字的接收数据信号与都数据槽函数连接
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Solt()));
    }
    //读取数据
    void TcpServer::readyRead_Solt(void)
    {
    QString buf;
    //读取
    buf = tcpSocket->readAll();
    ui->recvEdit->appendPlainText(buf);
    }
    TcpServer::~TcpServer()
    {
    delete ui;
    }
    //打开
    void TcpServer::on_openBu_clicked()
    {
    //监听
    tcpServer->listen(QHostAddress::Any,ui->portEdit->text().toUInt());
    }
    //发送数据
    void TcpServer::on_sendBu_clicked()
    {
    tcpSocket->write(ui->sendEdit->text().toLocal8Bit().data());
    }
    //关闭
    void TcpServer::on_closeBu_clicked()

    {
    tcpSocket->close();
    }
    步骤四:客户端编程

    1.创建 QTcpSocket 套接字对象
    2.使用套接字对象的成员函数去请求连接服务器。
    void connectToHost(const QHostAddress &address, quint16 port, openMode mode = ReadWrite);
    第一个参数为服务器 IP 地址,第二个参数为服务器端口号。第三个参数为打开方式,默认为可读可写
    函数功能:请求连接服务器连接成功后发出connected()信号,绑定槽函数connected_Solt()去操作socket。
    3.使用 write 函数向服务器发送数据,当 socket 接收缓冲区有新数据到来时
    会发出 readyRead()信号,为该信号添加槽函数以读取数据。
    4.断开与服务器的连接。

    class TcpClient : public QMainWindow
    {
    ....... private slots:
    void on_openBt_clicked();
    void connected_Solt(void);
    void readyRead_Solt(void);
    void on_sendEdit_2_clicked();
    void on_closeBt_clicked();
    };

    TcpClient::TcpClient(QWidget *parent) :
    QMainWindow(parent), ui(new Ui::TcpClient)
    {
    ui->setupUi(this);
    //创建 socket 对象
    tcpSocket = new QTcpSocket(this);
    }
    TcpClient::~TcpClient()
    {
    delete ui;
    }
    //打开(连接服务器)
    void TcpClient::on_openBt_clicked()
    {
    tcpSocket->connectToHost(ui->ipEdit->text(),ui->portEdit->text().toUInt());
    connect(tcpSocket,SIGNAL(connected()),this,SLOT(connected_Solt()));
    }
    //等待数据到来
    void TcpClient::connected_Solt(void)
    {
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Solt()));
    }
    //读取数据
    void TcpClient::readyRead_Solt(void)
    {
    ui->recvEdit->appendPlainText(tcpSocket->readAll());
    }
    //发送
    void TcpClient::on_sendEdit_2_clicked()
    {
    tcpSocket->write(ui->sendEdit->text().toLocal8Bit().data());
    }
    //关闭
    void TcpClient::on_closeBt_clicked()

    {
    tcpSocket->close();
    }
    编译运行成功,使用服务器和客户端通信如图:

  • 相关阅读:
    JAVA中线程同步的方法(4种)汇总
    java
    指定的元素已经是另一个元素的逻辑子元素。请先将其断开连接。(解决问题总结)
    无法将类型为“System.Windows.Controls.SelectedItemCollection”的对象强制转换为类型“System.Collections.Generic.IList`1
    foreach---集合已修改;可能无法执行枚举操作。
    WPF_View中控件使用单例ViewModel
    判断s2是否能够被通过s1做循环移位(rotate)得到的字符串是否包含
    多列转1列 SqlServer 实现oracle10g的 wmsys.wm_concat()--for xml path('')
    异步对象(XMLHttpRequest)的帮助脚本
    在vs2010使用EF出现CS0012: 类型“System.Data.Objects.DataClasses.EntityObject”在未被引用的程序集中定义
  • 原文地址:https://www.cnblogs.com/liyue3/p/14714321.html
Copyright © 2011-2022 走看看