Qt中网络编程的实现

目录
  • 一、tcp/IP协议簇与udp
    • 1、TCP/IP协议族
    • 2、udp
    • 3、常用的通讯协议小结
  • 二、Qt中的tcp(这里只展示代码)
    • 1、tcpsever
    • 2、tcpclient
  • 三、QT中的Udp

由于我没有系统的分享一些简单的计算机网络有关的,下面只是简单讲讲tcp/ip协议簇和udp

一、tcp/IP协议簇与udp

1、TCP/IP协议族

TCP/IP实际上是一个协同工作的通信家族,为网络通信提供通路。为方便讨论TCP/IP协议族,大体上分为三部分:

①、Internet协议(IP)。

②、传输控制协议(TCP)和用户数据报协议(UDP)。

③、处于TCP和UDP之上的一组应用协议。它们包括:Telnet,文件传送协议(FTP),域名服务协议(DNS)和简单的邮件传送程序(SMTP)等。

2、udp

udp协议(用户数据报协议),它与TCP协议完全相反。提供不可靠、无连接和基于数据报的服务。不可靠意味着UDP协议无法保证数据从发送端正确的发送到接收端。如果数据在中途丢失,或者目的端通过数据校验发现数据错误而将其丢弃,则UDP协议的应用程序通常要自己处理数据确认、超时重传等逻辑性。

3、常用的通讯协议小结

1.3.1、tcp/ip

tcp只需要知道它是一种通讯方式就可以了,还有一个udp,那这两者之间的关系是什么。TCP/IP协议是一个协议簇。里面包括很多协议的。UDP只是其中的一个。之所以命名为TCP/IP协议,因为TCP,IP协议是两个很重要的协议,就用他两命名了,tcp是打电话,udp是发短信。

Ip(网络之间互连的协议,外文是Internet Protocol的外语缩写,中文缩写为“网协”。缩写为IP),通过设置ip地址就可以去访问网络,用的最多的ip协议是ipv4(ip协议v版本4),还有一个版本为ipv6,ipv4不够用了,Ipv4版本是32位的,一般分成4段,内存中就是一个无符号32位的整数,ipv6的话就是一个64位的整数,通过位数就知道ipv4和ipv6的区别,能保存多少个的地址。只不过用户并不需要去搞清楚。

现在常用的ip是127.0.0.1这个样子,点分格式(一个字符串)。点所隔开的区间就是一个字符。Ip地址有ABC三类地址。前三段是用来确定路由器,确定主机连上外围网上的哪一个路由,最后一段用来确定主机,确定主机是这个路由器上的第多少台,最多255台,0一般是用来做网关的。

ip对应的还有一个子网掩码

子网掩码(subnet mask)又叫网络掩码、地址掩码、子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。子网掩码--屏蔽一个IP地址的网络部分的"全1"比特模式。

对于A类地址来说,默认的子网掩码是255.0.0.0;

对于B类地址来说默认的子网掩码是255.255.0.0;

对于C类地址来说默认的子网掩码是255.255.255.0。

子网掩码,一般是255.255.255.0。

ip地址的前三段来确定路由器,最后一段是主机位置。所以子网掩码理解为子网遮罩编码。

1.3.2、Socket

pc机对应在网络上就是一台主机,在这台Pc机上面会有多个进程需要访问网络,所以需要在Pc机的操作系统上面去有处理网络的东西,前人就定了一个“套接字”来专门处理网络(源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字)。把一个主机拆分为N个网络端口(Port)一共会有65536个,short的最大范围,在这些端口当中,要注意0-5000的端口一般不用,用来给操作系统的进程来使用的。一般会用靠后一点的端口,这样比较安全,当然还有一些端口,比如8080端口也会用的比较多,一个进程只能占用一个端口,不能多进程占用同一个端口的情况,一个进程可以占用多个端口的,或者严谨一点,同一时刻一个端口只能由一个进程使用。网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。

1.3.3、tcp通信模型

c/s模型,客户端(c)/服务器(s)模型,一个服务器来对应多个客户端的处理,一对多的关系。以下步骤没有特殊指明,服务器和客户端是都需要有的步骤:

1.准备工作,根据自己使用语言所有库函数导入;

2. 确定版本信息,要确定socket版本,ip是有v4和v6两个版本的;

3. 创建socket,使用socket函数

4. 初始化协议地址簇 ;

5. 绑定,使用bind函数,把协议地址簇和socket绑定在一起,客户端不要绑定;

6. 服务器端有,需要监听 listen函数,客户端不需要这一步;

7. 服务器端需要接受连接,客户端需要连接服务器;

8. 连接完成之后,开始通讯,收发数据;

9. 通讯完成后关闭socket;

二、Qt中的tcp(这里只展示代码)

开始前在项目的.pro文件中加入这个network

1、tcpsever

tcpsever.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QNetworkInterface>//网络信息
#include <QHostAddress>//id地址
#include <QTcpServer> //tcp协议
#include <QTcpSocket> //socket套接字
#include <QDebug>
#include <QMessageBox>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_pushButton_listen_clicked();

    void on_pushButton_send_clicked();
    void newconnectslot();//连接
    void readyRead_Slot();//读取信息
    void disconnected_Slot();//断开
private slots:
    QString list_all_IPV4();

private:
    Ui::Widget *ui;
    //2、设置服务端和接收客户端的对象
    QTcpServer *tcpServer;
    QTcpSocket *tcpSocket;
};

#endif // WIDGET_H

tcpsever.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //3、创建服务器对象
    tcpSocket=NULL;
    tcpServer=new QTcpServer(this);
    //5、有客户端连接服务器发送信号
    connect(tcpServer,
            SIGNAL(newConnection()),
            this,
            SLOT(newconnectslot()));
    QMessageBox::information(this,"本机联网端口显示",this->list_all_IPV4());
}

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

void Widget::on_pushButton_listen_clicked()
{
    //4、开始监听
    QString sever_Address = ui->lineEdit_address->text();
    quint16 port          = ui->lineEdit_port->text().toInt();
    QHostAddress host     = QHostAddress(sever_Address);
    if(!tcpServer->isListening()){
        //监听绑定的ip地址
        if(!tcpServer->listen(host,port))
        {
            qDebug()<<tcpServer->errorString();
            return;
        }else{
            qDebug()<<"监听成功";
            ui->pushButton_listen->setText("停止监听");
        }
    }else{
        tcpServer->close();
        ui->pushButton_listen->setText("开始监听");
    }
}

QString Widget::list_all_IPV4(){
            QString str;
            QList<QHostAddress> list=QNetworkInterface::allAddresses();     //获取本机的所有网卡的ip地址
            foreach (QHostAddress address, list)
            {
                if(address.isNull())
                    continue;
                QAbstractSocket::NetworkLayerProtocol portocol=address.protocol();
                //只提取IPv4地址
                if(portocol!=QAbstractSocket::IPv4Protocol)
                    continue;

                str = str +'\n\t'+address.toString() + '\n\t\t';
            }
            return str;
};

void Widget::newconnectslot(){
    //6、接受客户端
    tcpSocket = tcpServer->nextPendingConnection();
    QString client_Info = "客户端:" + tcpSocket->peerAddress().toString()
                          +" "+
                          "端口号:"    + QString::number(tcpSocket->peerPort());
    ui->textBrowser_clientInfo->setText(client_Info);
    //发送信号和读取关联
    connect(tcpSocket,
            SIGNAL(readyRead()),
            this,
            SLOT(readyRead_Slot()));
    //断开信号关联客户端
    connect(tcpSocket,
            SIGNAL(disconnected()),
            this,
            SLOT(disconnected_Slot()));
};

void Widget::on_pushButton_send_clicked()
{
    if(tcpSocket != nullptr)
    {
        if(tcpSocket->isWritable())
        {
            QString send = ui->plainTextEdit_sendInfo->toPlainText();

            QByteArray sendarr = send.toLocal8Bit();//本地字符集与Unicode的转换

            tcpSocket->write(sendarr);
        }
    }
}

void Widget::readyRead_Slot(){
    if(tcpSocket != nullptr)
    {
        if(tcpSocket->isReadable())
        {
           QByteArray recvAll = tcpSocket->readAll();//将数据全部读取

           QString str = str.fromLocal8Bit(recvAll.data());

           ui->textBrowser_recv->append(str);
        }
    }

};

void Widget::disconnected_Slot(){
    QMessageBox::information(this,"Client Close Signal","有客户离开");
};

2、tcpclient

tcpclient,h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QNetworkInterface>//网络信息
#include <QHostAddress>//id地址
#include <QTcpServer> //tcp协议
#include <QTcpSocket> //socket套接字
#include <QDebug>
#include <QMessageBox>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_pushButton_listen_clicked();
    void on_pushButton_send_clicked();

    void readyRead_Slot();//读取信息
    void disconnected_Slot();//断开

private:
    Ui::Widget *ui;
    QTcpSocket *client;
    bool socket_state;
};

#endif // WIDGET_H

tcpclient.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    client = new QTcpSocket(this);
    socket_state = false;

    connect(client,
            SIGNAL(disconnected()),
            this,
            SLOT(disconnected_Slot()));

    connect(client,
            SIGNAL(readyRead()),
            this,
            SLOT(readyRead_Slot()));
}

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

void Widget::on_pushButton_listen_clicked()
{
    QString ipAddress = ui->lineEdit_address->text();
    qint16 port = ui->lineEdit_port->text().toInt();

    if(!socket_state)
    {
        client->connectToHost(ipAddress,port);
        if(client->waitForConnected(3000)){//等待3s,连不上会返回假
            ui->pushButton_listen->setText("断开连接");
            socket_state = true;
        }else{
            qDebug()<<client->errorString();
            return;
        }
    }else{
        client->close();
        QMessageBox::information(this,"消息提示","已经离开!",QMessageBox::Yes);
        ui->pushButton_listen->setText("连接");
        socket_state = false;
    }
}

void Widget::readyRead_Slot(){
    QByteArray data=client->readAll();
    QString str=str.fromLocal8Bit(data.data());
    ui->textBrowser_recv->append(str);

};

void Widget::disconnected_Slot(){
     qDebug()<<"离开";
}

void Widget::on_pushButton_send_clicked()
{
    QString datastr = ui->plainTextEdit_sendInfo->toPlainText();
    QByteArray da = datastr.toLocal8Bit();

    if(client->isOpen() && client->isValid()){
        client->write(da);
    }
}

三、QT中的Udp

初始操作同TCP操作

udp_test.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

//1、包含相关的头文件
#include <QHostAddress>
#include <QUdpSocket>
#include <QDebug>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_pushButtonSend_clicked();
    void readyReadSlot();
    void on_pushButtonCLose_clicked();

private:
    Ui::Widget *ui;
    //2、定义udp对象
    QUdpSocket *udpSocket;
};

#endif // WIDGET_H

udp_test.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //3、创建对象
    udpSocket=new QUdpSocket(this);

    //4、关联读取的信号与槽
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyReadSlot()));

}

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

void Widget::on_pushButtonSend_clicked()
{
    udpSocket->writeDatagram(ui->plainTextEdit_sendInfo->toPlainText().toLocal8Bit(),//内容
                             QHostAddress(ui->lineEditIp->text()),//发送ip
                             ui->lineEditPort->text().toInt());//发送的地址
}

void Widget::on_pushButtonCLose_clicked()
{
    udpSocket->bind(ui->lineEditPort_2->text().toInt());
}

void Widget::readyReadSlot(){
  quint64 size = udpSocket->bytesAvailable();//读取发过来的消息大小
  QByteArray ba;
  ba.resize(size);
  QHostAddress address;
  quint16 port;

  udpSocket->readDatagram(ba.data(),size,&address,&port);
  QString str = QString::fromLocal8Bit(ba.data());

  ui->textEdit_recvInfo->append(str);
}

到此这篇关于Qt中网络编程的实现的文章就介绍到这了,更多相关Qt网络编程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • QT网络编程Tcp下C/S架构的即时通信实例

    先写一个客户端,实现简单的,能加入聊天,以及加入服务器的界面. #ifndef TCPCLIENT_H #define TCPCLIENT_H #include <QDialog> #include <QListWidget> #include <QLineEdit> #include <QPushButton> #include <QLabel> #include <QGridLayout> #include <QtNetWo

  • 计算机网络编程MQTT协议基础原理详解

    目录 什么是 MQTT 协议 MQTT 基础 发布 - 订阅模式 可拓展性 消息过滤 基于主题的过滤 基于内容的过滤 基于类型的过滤 MQTT 与消息队列的区别 MQTT 重要概念 MQTT client MQTT broker MQTT Connection 消息报文 CONNECT CONNACK 消息类型 发布 订阅 确认消息 退订 确认退订 聊聊 Topic 通配符 单级通配符 多级通配符 之前有位读者给我留言说想要了解一下什么是 MQTT 协议,顺便还把我夸了一把,有点不好意思啦. 那

  • QT网络编程UDP下C/S架构广播通信(实例讲解)

    QT有封装好的UDP协议的类,QUdpSocket,里面有我们想要的函数接口.感兴趣的话,可以看看. 先搞服务端吧,写一个子类,继承QDialog类,起名为UdpServer类.头文件要引用我们上边说的QUdpSocket这个类,还有我们想要的布局的类. #ifndef UDPSERVER_H #define UDPSERVER_H #include <QDialog> #include <QLabel> #include <QLineEdit> #include &l

  • Qt中网络编程的实现

    目录 一.tcp/IP协议簇与udp 1.TCP/IP协议族 2.udp 3.常用的通讯协议小结 二.Qt中的tcp(这里只展示代码) 1.tcpsever 2.tcpclient 三.QT中的Udp 由于我没有系统的分享一些简单的计算机网络有关的,下面只是简单讲讲tcp/ip协议簇和udp 一.tcp/IP协议簇与udp 1.TCP/IP协议族 TCP/IP实际上是一个协同工作的通信家族,为网络通信提供通路.为方便讨论TCP/IP协议族,大体上分为三部分: ①.Internet协议(IP).

  • QT UDP网络编程实现简单消息传输

    本文实例为大家分享了QT UDP实现简单消息传输的具体代码,供大家参考,具体内容如下 这几天看了下Qt的udp,顺便实现了下简单的消息传输,看起来比较简单. UDP服务器: 截图如下: 代码: server.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include<QUdpSocket> #include<QtNetwork> #include<QLabel> #include<QP

  • 深入了解Golang网络编程Net包的使用

    目录 1.TCP 服务 2.TCP 连接在系统调用层面的实现 3.Go中TCP连接的实现 4.结语 ​最近做了一个项目,其中用到了网络编程,下面和大家分享下在Go中网络编程的实现.在Go中, 网络编程主要通过 net 包实现.支持 包括TCP/IP.UDP.域名解析和Unix域socket等连接,此外,还通过 net/http ,net/rpc 等提供了 HTTP,RPC等主流应用层的连接协议. 1.TCP 服务 TCP 是最常用的网络连接方式,以 TCP 连接为例,一个简单的 TCP 连接代码

  • Qt实现TCP网络编程

    本文实例为大家分享了Qt实现TCP网络编程的具体代码,供大家参考,具体内容如下 1.Qt中的TCP客户端编程 Qt中的TCP客户端编程: 对于Qt编程而言,网络只是数据传输的通道Qt提供了QTcpSocket类(封装了TCP协议细节)将QTcpSocket的对象当做黑盒使用,进行数据收发 QTcpSocket的使用方式: 1.连接服务端主机(connectToHost())2.发送数据/接受数据(write()/read())3.关闭连接(close()) QTcpSocket的注意事项: 默认

  • Qt网络编程实现TCP通信

    Qt网络编程实现TCP通信,供大家参考,具体内容如下 标签(空格分隔): Tcp通信 一.Tcp简介 (1)TCP(Transmission Control Protocol,传输控制协议)TCP是一个用于数据传输的传输层网络协议,多个网络协议包括(HTTP和FTP都是基于TCP协议),TCP是面向数据流和连接的可靠的传输协议,它区别于传输层的另外一个协议UDP(具体可看—Qt简单实现UDP通信) . (2)QTcpSocket继承自QAbstractSocket,与QUdpSocket传输的数

  • C++中Socket网络编程实例详解

    C++中Socket网络编程实例详解 现在几乎所有C/C++的后台程序都需要进行网络通讯,其实现方法无非有两种:使用系统底层socket或者使用已有的封装好的网络库.本文对两种方式进行总结,并介绍一个轻量级的网络通讯库ZeroMQ.  1.基本的Scoket编程 关于基本的scoket编程网络上已有很多资料,作者在这里引用一篇文章中的内容进行简要说明. 基于socket编程,基本上就是以下6个步骤: 1.socket()函数 2.bind()函数 3.listen().connect()函数 4

  • C#网络编程中常用特性介绍

    特性一:委托 委托是C#语言中特有的概念,相当于C/C++中的函数指针,与C/C++中函数指针的不同之处是:委托是面向对象的.类型安全的和保险的,是引用类型.因此,对委托的使用要 “先定义.后声明,接着实例化.然后作为参数传递给方法,最后才能使用”. 1.定义委托使用关键字delegate: delegate  void SomeDelegate(type1 para1,......typen paran); 2.声明委托: SomeDelegate  d; 3.实例化委托: d=new Som

  • 解析C#网络编程中的Http请求

    本篇分享简单介绍C#中的Http请求,前几天帮朋友的项目封装ApiHelper,我粗糙的结果就如下,想想我真的是差的太远了.还有一位架构师也在封装这个Helper , 所以最后的结果当然是使用大牛的封装,这篇分享后,准备学习下他的封装,配置,错误处理机制等思想.不过这次也使我对C#网络编程了解的更多,算是一次学习经历吧.真心喜欢和老司机合作,下一阶段将会持续跟这位朋友学习项目底层的封装,和他谦虚的态度,有这样的机会也是幸运的. 你可以将其封装成自己的HttpHelper,经朋友建议,统一Http

随机推荐