QT网络编程

 1.回顾linux的网络编程
            tcp服务器:  socket--》bind-->listen-->accept-->read/write-->close
            tcp客户端:  socket--》bind-->connect-->read/write-->close

   2.QT中的tcp
         如果用到QT的网络编程,必须在QT工程中添加  QT += network(打开.pro文件,把这个库加进去)
         (1)涉及到类
                  QTcpServer --》表示tcp服务器
                  QTcpSocket --》表示tcp套接字
        (2)流程思路
                 服务器流程
                      第一步:创建QTcpServer对象,然后调用listen方法绑定并监听
                                       QTcpServer::QTcpServer(QObject *parent = nullptr)
                                       //绑定并监听
                                       bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
                                                          参数:  address --》你要绑定的ip地址 QHostAddress类是用来表示ip地址的一个类
                                     QHostAddress::QHostAddress(const QString &address)
                                                                                                                     参数:address --》ip地址 
                                                                   port --》你要绑定的端口号
                     第二步:如果有新的客户端连接服务器,QTcpServer对象会自动触发[signal] void QTcpServer::newConnection()信号,程序员主动关联这个信号,在槽函数中调用QTcpSocket *QTcpServer::nextPendingConnection()产生新的套接字
                     第三步:使用刚才第二步产生的新套接字去跟对应的客户端通信
                                                发送信息: write() --》跟前面学习文件IO是一模一样
                                                接收信息: read()/readAll() --》跟前面学习文件IO是一模一样
                                                注意:接收信息必须通过信号与槽来接收,当对方有发送信息过来,QTcpSocket对象会自动触发[signal] void QIODevice::readyRead(),程序员需要关联该信号,在槽函数中调用read/readAll去接收对方的信息
                     第四步:关闭套接字
                                                void QAbstractSocket::close()

                客户端流程QTcpClient
                     第一步:创建QTcpSocket对象,然后调用bind方法绑定自己的ip和端口号
                                     QTcpSocket(QObject *parent = nullptr)
                                    //绑定自己的ip和端口号
                                    bool QAbstractSocket::bind(const QHostAddress &address, quint16 port = 0)
                                                           参数:  address --》你要绑定的ip地址 QHostAddress类是用来表示ip地址的一个类
                                                                                        QHostAddress::QHostAddress(const QString &address)
                                                                                                                     参数:address --》ip地址 
                                                                    port --》你要绑定的端口号
                    第二步:连接服务器
                                  void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port)
                                                          参数:address  --》服务器的ip地址
                                                                    port --》服务器的端口号
                    第三步:使用第一步创建的套接字去跟服务器通信
                                                发送信息: write() --》跟前面学习文件IO是一模一样
                                                接收信息: read()/readAll() --》跟前面学习文件IO是一模一样
                                                注意:接收信息必须通过信号与槽来接收,当对方有发送信息过来,QTcpSocket对象会自动触发[signal] void QIODevice::readyRead(),程序员需要关联该信号,在槽函数中调用read/readAll去接收对方的信息
                   第四步:关闭套接字
                                                void QAbstractSocket::close()
          (3)其他常用的方法
                        第一个:获取对方的ip和端口号
                                       //获取对方的ip
                                       QHostAddress QAbstractSocket::peerAddress() const   
                                                      返回值: 返回对方的ip地址
                                                                    QString QHostAddress::toString() const  //可以把ip地址转换成熟悉的字符串格式(点分十进制ip)
                                      //获取对方的端口号
                                      quint16 QAbstractSocket::peerPort() const
                                                     返回值:返回对方的端口号
          (4)多个客户端连接同一个服务器
                       需要把所有连接成功的客户端套接字保存起来
          (5)判断客户端/服务器断开连接
                      客户端/服务器断开连接,QTcpSocket对象会自动触发[signal] void QAbstractSocket::disconnected()信号,我们只需要关联这个信号,在槽函数中去处理断开以后的事情就可以了

 tcp单向通信

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //设置标题
    this->setWindowTitle("我是服务器");
    //绑定并监听
    server.listen(QHostAddress("192.168.26.2"),10000);
    //关联newConnection()信号
    connect(&server,SIGNAL(newConnection()),this,SLOT(newclientlink()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
//如果有新的客户端连接服务器,这个槽函数就会被自动调用
void MainWindow::newclientlink()
{
    qDebug()<<"新的客户端连接服务器了";
    //产生新的套接字用于跟这个客户端通信
    p=server.nextPendingConnection();

    //获取连接成功的这个客户端的ip和端口号
    QString ipstr=p->peerAddress().toString();
    quint16 portnum=p->peerPort();

    //在横向列表框中把这个客户端的信息显示出来
    QString str=QString("%1@%2").arg(ipstr).arg(portnum);
    ui->listWidget->addItem(str);

    //接收信息--》反面教材,直接调用read/readAll接收
    //QByteArray buf=p->readAll();  //根本收不到信息
    //关联readyRead信号
    connect(p,SIGNAL(readyRead()),this,SLOT(recvclientmsg()));
}

//接收客户端发送过来的信息
void MainWindow::recvclientmsg()
{
    QByteArray buf=p->readAll();
    //把接收的信息在文本编辑框中显示出来
    ui->textEdit->setText(buf);
}

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //设置标题
    this->setWindowTitle("我是客户端张三");
    //绑定ip和端口号
    sock.bind(QHostAddress("192.168.26.2"),20000);
}

MainWindow::~MainWindow()
{
    delete ui;
}

//连接服务器
void MainWindow::on_linkbt_clicked()
{
    //获取输入的ip和端口号
    QString ipstr=ui->iple->text();
    QString portstr=ui->portle->text();
    sock.connectToHost(QHostAddress(ipstr),portstr.toInt());
}
//发送信息给服务器
void MainWindow::on_sendbt_clicked()
{
    //获取文本编辑框中输入的内容
    QString str=ui->textEdit->toPlainText();
    //发送给服务器
    sock.write(str.toUtf8());
}

tcp双向通信

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //设置标题
    this->setWindowTitle("我是服务器");
    //绑定并监听
    server.listen(QHostAddress("192.168.26.2"),10000);
    //关联newConnection()信号
    connect(&server,SIGNAL(newConnection()),this,SLOT(newclientlink()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
//如果有新的客户端连接服务器,这个槽函数就会被自动调用
void MainWindow::newclientlink()
{
    qDebug()<<"新的客户端连接服务器了";
    //产生新的套接字用于跟这个客户端通信
    p=server.nextPendingConnection();

    //获取连接成功的这个客户端的ip和端口号
    QString ipstr=p->peerAddress().toString();
    quint16 portnum=p->peerPort();

    //在横向列表框中把这个客户端的信息显示出来
    QString str=QString("%1@%2").arg(ipstr).arg(portnum);
    ui->listWidget->addItem(str);

    //接收信息--》反面教材,直接调用read/readAll接收
    //QByteArray buf=p->readAll();  //根本收不到信息
    //关联readyRead信号
    connect(p,SIGNAL(readyRead()),this,SLOT(recvclientmsg()));
}

//接收客户端发送过来的信息
void MainWindow::recvclientmsg()
{
    QByteArray buf=p->readAll();
    //把接收的信息在文本编辑框中显示出来
    ui->textEdit->setText(buf);
}

//发送信息给客户端
void MainWindow::on_pushButton_clicked()
{
    //获取文本编辑框中输入的内容
    QString buf=ui->textEdit_2->toPlainText();
    p->write(buf.toUtf8());
}

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //设置标题
    this->setWindowTitle("我是客户端张三");
    //绑定ip和端口号
    sock.bind(QHostAddress("192.168.26.2"),20000);
    //关联readyRead信号
    connect(&sock,SIGNAL(readyRead()),this,SLOT(recvservermsg()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

//连接服务器
void MainWindow::on_linkbt_clicked()
{
    //获取输入的ip和端口号
    QString ipstr=ui->iple->text();
    QString portstr=ui->portle->text();
    sock.connectToHost(QHostAddress(ipstr),portstr.toInt());
}
//发送信息给服务器
void MainWindow::on_sendbt_clicked()
{
    //获取文本编辑框中输入的内容
    QString str=ui->textEdit->toPlainText();
    //发送给服务器
    sock.write(str.toUtf8());
}
//接收服务器发送过来的信息
void MainWindow::recvservermsg()
{
    QByteArray recvbuf=sock.readAll();
    //把接收的信息在文本编辑框中显示出来
    ui->textEdit_2->setText(recvbuf);
}

 tcp多个客户端连接服务器

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //设置标题
    this->setWindowTitle("我是服务器");
    //绑定并监听
    server.listen(QHostAddress("192.168.26.2"),10000);
    //关联newConnection()信号
    connect(&server,SIGNAL(newConnection()),this,SLOT(newclientlink()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
//如果有新的客户端连接服务器,这个槽函数就会被自动调用
void MainWindow::newclientlink()
{
    qDebug()<<"新的客户端连接服务器了";
    //产生新的套接字用于跟这个客户端通信
    p=server.nextPendingConnection();

    //顺便把这个套接字存放到容器中
    clientlist.append(p);

    //获取连接成功的这个客户端的ip和端口号
    QString ipstr=p->peerAddress().toString();
    quint16 portnum=p->peerPort();

    //在横向列表框中把这个客户端的信息显示出来
    QString str=QString("%1@%2").arg(ipstr).arg(portnum);
    ui->listWidget->addItem(str);

    //接收信息--》反面教材,直接调用read/readAll接收
    //QByteArray buf=p->readAll();  //根本收不到信息
    //关联readyRead信号,为了接收信息
    connect(p,SIGNAL(readyRead()),this,SLOT(recvclientmsg()));
    //关联disconnected(),为了判断客户端是否断开了
    connect(p,SIGNAL(disconnected()),this,SLOT(someclientunlink()));
}

//接收客户端发送过来的信息
void MainWindow::recvclientmsg()
{
    //清空字符串
    allclientmsg.clear();

    //获取信号的发送者
    QTcpSocket *somesock=qobject_cast<QTcpSocket *>(sender());
    QByteArray buf=somesock->readAll();
    QString msgstr(buf);
    //判断收到的信息
    if(msgstr=="getlist")  //说明某个客户端想让服务器发送在线好友信息
    {
        allclientmsg.append("getlist@");
        //遍历容器,把所有的客户端信息拼接成字符串然后发送给对应的客户端
        //ip@端口号\nip@端口号\nip@端口号
        for(int i=0; i<clientlist.size(); i++)
        {
            QString ipstr=clientlist.at(i)->peerAddress().toString();
            quint16 portnum=clientlist.at(i)->peerPort();
            QString str=QString("%1@%2@").arg(ipstr).arg(portnum);
            allclientmsg.append(str);
        }
        //把拼接好的所有客户端信息发送给对应的客户端
        somesock->write(allclientmsg.toUtf8());
    }
    else  //其它信息
    {
        //得到这个客户端的ip以及端口号,拼接显示
        QString ipstr=somesock->peerAddress().toString();
        quint16 portnum=somesock->peerPort();
        QString str=QString("%1@%2@%3").arg(ipstr).arg(portnum).arg(msgstr);
        //把接收的信息在文本编辑框中显示出来
        //ui->textEdit->setText(str); //setText方法会覆盖之前显示的内容
        ui->textEdit->append(str); //append会把新信息追加到后面
    }

}

//发送信息给客户端
void MainWindow::on_pushButton_clicked()
{
    int i;
    //遍历容器,找到我刚才在横向列表框中点击的那个客户端对应的套接字
    for(i=0; i<clientlist.size(); i++)
    {
        QString ipstr=clientlist.at(i)->peerAddress().toString();
        quint16 portnum=clientlist.at(i)->peerPort();
        QString str=QString("%1@%2").arg(ipstr).arg(portnum);
        //跟刚才你点击进行比较
        if(str==someclientmsg)
            break;
    }
    //获取文本编辑框中输入的内容
    QString buf=ui->textEdit_2->toPlainText();
    clientlist.at(i)->write(buf.toUtf8());
}
//某个客户端断开连接了
void MainWindow::someclientunlink()
{
    //获取信号的发送者
    QTcpSocket *somesock=qobject_cast<QTcpSocket *>(sender());
    QString ipstr=somesock->peerAddress().toString();
    quint16 portnum=somesock->peerPort();
    QString str=QString("%1@%2").arg(ipstr).arg(portnum);
    //从在线客户端列表框中删除这个客户端的信息
    //先找到这个列表项
    QList<QListWidgetItem *> itemlist=ui->listWidget->findItems(str,Qt::MatchContains);
    int row=ui->listWidget->row(itemlist.at(0));
    ui->listWidget->takeItem(row);
    //从QList容器中删除这个客户端的套接字
    clientlist.removeOne(somesock);
}
//单击某个列表项
void MainWindow::on_listWidget_itemClicked(QListWidgetItem *item)
{
    someclientmsg=item->text();
}

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //设置标题
    this->setWindowTitle("我是客户端张三");
    //绑定ip和端口号
    sock.bind(QHostAddress("192.168.26.2"),20000);
    //关联readyRead信号
    connect(&sock,SIGNAL(readyRead()),this,SLOT(recvservermsg()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

//连接服务器
void MainWindow::on_linkbt_clicked()
{
    //获取输入的ip和端口号
    QString ipstr=ui->iple->text();
    QString portstr=ui->portle->text();
    sock.connectToHost(QHostAddress(ipstr),portstr.toInt());
}
//发送信息给服务器
void MainWindow::on_sendbt_clicked()
{
    //获取文本编辑框中输入的内容
    QString str=ui->textEdit->toPlainText();
    //发送给服务器
    sock.write(str.toUtf8());
}
//接收服务器发送过来的信息
void MainWindow::recvservermsg()
{
    QByteArray recvbuf=sock.readAll();
    QString str(recvbuf);
    //把收到的信息做字符串的切割
    QStringList msglist=str.split('@');
    //判断服务器发送过来的信息类型
    if(msglist.at(0)=="getlist") //说明收到是服务器发过来好友列表
    {
        //清空横向列表框
        ui->friendlist->clear();
        //在横向列表框中显示好友信息
        for(int i=1; i<msglist.size()-1; i++)
            ui->friendlist->addItem(msglist.at(i));
    }
    else if(msglist.at(0)=="msg") //说明服务器发过来的是字符串信息
    {

    }
    else if(msglist.at(0)=="emoji") //说明服务器发过来的是表情包序号
    {

    }
    else if(msglist.at(0)=="file")  //说明服务器发过来的是文件
    {

    }
    //把接收的信息在文本编辑框中显示出来
    //ui->textEdit_2->setText(recvbuf);
    ui->textEdit_2->append(recvbuf);
}
//刷新好友信息
void MainWindow::on_flushbt_clicked()
{
    //给服务器发送指定的字符串
    sock.write("getlist");
}

 udp通信

1.流程
            发送/接收端
         第一步: 创建QUdpSocket对象,绑定ip和端口号
                        QUdpSocket::QUdpSocket(QObject *parent = nullptr)
                        //绑定自己的ip和端口号
                        bool QAbstractSocket::bind(const QHostAddress &address, quint16 port = 0)
                                                           参数:  address --》你要绑定的ip地址 QHostAddress类是用来表示ip地址的一个类
                                                                                        QHostAddress::QHostAddress(const QString &address)
                                                                                                                     参数:address --》ip地址 
                                                                    port --》你要绑定的端口号
         第二步: 利用刚才的套接字收发信息
                       发送信息
                             qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
                             qint64 QUdpSocket::writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)
                                                  返回值:成功发送的字节数
                                                     参数:data --》你要发送的字符串
                                                               size --》发送的字节数
                                                               address --》对方的ip
                                                               port --》对方的端口号
                       接收信息
                            qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize)
                                                 返回值:成功收到的字节数
                                                    参数:data --》存放接收的信息                    
                                                              maxSize --》接收的字节数
          第三步:关闭
                       void QAbstractSocket::close()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hqb_newfarmer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值