基于QT的实现TCP的网络通信(服务器端)

首先介绍一下TCP,UDP的特点:

TCP是面向连接的流式传输协议,UDP是面向无连接的报式传输协议

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

TCP(传输控制协议)

  • 面向连接:在数据传输之前,TCP会建立一条可靠的连接,以确保数据的有序传输。
  • 流式传输:TCP将数据视为连续的字节流,不保留数据报边界。

-----流式传输协议是一种用于在网络上传输连续数据流的协议。它允许数据以一种连续的、类似于流水的方式进行传输,而不是 以离散的数据包形式进行传输。

a连续性:流式传输协议将数据视为一个连续的流,而不是独立的数据包。这意味着数据可以以一种不间断的方式进行传输,从而减少了传输延迟。

b实时性:由于数据是连续传输的,流式传输协议适用于实时性要求较高的应用,如音频和视频流媒体。

c顺序性:流式传输协议通常要求数据按照正确的顺序进行传输,以确保数据的完整性和准确性。

d可靠性:为了保证数据的可靠性,流式传输协议通常采用一些机制,如错误检测和纠正、重传等。

  • 可靠性:TCP通过确认、重传和超时机制来保证数据的可靠传输。
  • 有序性:TCP确保数据以正确的顺序到达目的地。
  • 流量控制:TCP使用滑动窗口机制来控制发送方的发送速度,以避免接收方的缓冲区溢出。
  • 拥塞控制:TCP使用拥塞控制算法来避免网络拥塞,并根据网络状况调整发送速率。

UDP(用户数据报协议)

  • 面向无连接:UDP不建立连接,直接将数据报发送到目的地,不保证数据的有序传输。
  • 报式传输:UDP保留数据报的边界,将数据划分为独立的数据报进行传输。
  • 不可靠性:UDP不保证数据的可靠传输,不进行确认、重传和超时处理。
  • 无序性:UDP不保证数据的有序到达,接收方可能收到乱序的数据报。
  • 无流量控制:UDP不进行流量控制,发送方可以以任意速度发送数据报。
  • 无拥塞控制:UDP不进行拥塞控制,不根据网络状况调整发送速率。

TCP和UDP是两种不同的传输层协议,它们在可靠性、有序性、流量控制和拥塞控制等方面存在差异。TCP适用于对可靠性要求较高的应用,如文件传输和远程登录;而UDP适用于对实时性要求较高的应用,如语音通信和视频流传输。

QT服务器端

窗口搭建

首先在QT中新建一个项目,基类为Qmainwindow

  然后在mainwindow.ui中完成以下窗口的搭建

 要在在mainwindow.ui中实现以下窗口

首先在最上端放一个QWidget在里面放入Qlabel输入端口QLineEditObjectnameport表示输入的端口号,再放一个QPushbutton输入监听ObjectnamesetListen

 然后在下面放一个QGroupBox,name改为历史信息表示服务器客户端发送的信息都会保存在这,在里面放一个TextEdit,Objectname改为record再水平布局

下面类似,TextEditObjectname改为msg表示服务器要发送的信息,每次点击发送清空发送的信息框中的内容

最下面还是先放一个QGroupBox,中间放一个pushbutton输入发送,Objectname改为sendMsg,再水平布局

最后整体 垂直布局,这样服务器的窗口就搭建成功了

代码部分

首先,要想在QT中完成TCP的传输协议,不论是客户端还是服务器我们都先要在QtSever.pro中的

QT += core gui 后加入 network如图

mianwindow.h

 在mainwindow.h中,我们要加入如图所示头文件,并创建两个指针类型的QTcpSever和QTcpSocket类的对象,*m_s,和*tcp;

这里的slots内的是槽函数,我们可以右键ui中的按钮转到槽函数,可以自动在头文件中定义;

mainwindow.cpp

 首先在构造函数中默认端口号是8899;

  设置窗口的标题是服务器

首先实例化QTcpsever类,m_s;

如果客户端那边发来一个连接请求,m_s就会收到一个newConnection的信号,这里实现一个匿名函数  用QTcpSever类的nextPendingConnction函数返回套接字tcp 

如果客户端有内容发送过来,tcp就会收到一个readyRead的信号,定义一个QByteAttay的data的数据类型去接受发送来的内容,把读到的内容追加到record文本框中

如果客户端断联,tcp会收到disconncet的信号,使用匿名函数进行tcp的关闭close()和资源释放deleteLater()

实现头文件中的两个槽函数,如果点击sectListen,会将窗口中port文本框的内容赋值给一个unsined short 类型 的port,   再使用QTcpSever类中的listen监听客户端发送的ip和端口号;

如果此时正在监听那么就将监听按钮设置为不可按的状态

如果点击sendMsg,首先窗口中的msg赋值给Qstring类型的msg,tcp里的write函数发送给客户端,这时窗口的record就可以进行文本追加操作了,记录服务器发送的文本

那么到这里操作就写完了,以下是。h和.cpp的完整代码

服务器完整代码
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QTcpServer>
#include <QTcpSocket>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_setListen_clicked();

    void on_sendMsg_clicked();

private:
    Ui::MainWindow *ui;
    QTcpServer *m_s;
    QTcpSocket *tcp;

};

#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->port->setText("8899");
    setWindowTitle("服务器");

    m_s = new QTcpServer(this);//实例化

    connect(m_s,&QTcpServer::newConnection,this,[=](){//如果收到客户端的连接,就
        tcp = m_s->nextPendingConnection();//返回套接字用于通信的 tcp

      connect(tcp,&QTcpSocket::readyRead,this,[=](){//如果tcp收到一个readyRead信号就
            QByteArray data = tcp->readAll();//把内容读出来放到data里
            ui->record->append("客户端say:" + data);//把内容追加到record中
        });

    connect(tcp,&QTcpSocket::disconnected,this,[=](){//如果套接字收到断联消息,就关闭套接字并释放
        tcp->close();
        tcp->deleteLater();
    }) ;

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

void MainWindow::on_setListen_clicked()
{
    unsigned short port = ui->port->text().toUShort();
    m_s->listen(QHostAddress::Any,port);
    ui->setListen->setDisabled(true);
}

void MainWindow::on_sendMsg_clicked()
{
    QString msg = ui->msg->toPlainText();
    tcp->write(msg.toUtf8());
    ui->record->append("服务器say:" + msg);
}
main.cpp
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

最后编译的效果

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QT中,可以使用QTcpSocket和QTcpServer类来实现基于TCP网络通信,其中QTcpSocket用于客户端,QTcpServer用于服务器端服务器端实现步骤: 1. 创建一个QTcpServer对象,并监听指定的IP地址和端口号。 2. 监听到新的连接时,创建一个QTcpSocket对象,并将其与客户端进行连接。 3. 通过QTcpSocket对象进行数据的发送和接收。 客户端实现步骤: 1. 创建一个QTcpSocket对象。 2. 使用QTcpSocket对象与服务器端进行连接。 3. 通过QTcpSocket对象进行数据的发送和接收。 下面是一个简单的示例代码,展示了服务器端和客户端的实现服务器端代码: ```cpp QTcpServer server; server.listen(QHostAddress::Any, 1234); // 监听IP地址和端口号 connect(&server, &QTcpServer::newConnection, [&server]() { QTcpSocket* clientSocket = server.nextPendingConnection(); connect(clientSocket, &QTcpSocket::readyRead, [clientSocket]() { QByteArray data = clientSocket->readAll(); // 处理接收到的数据 qDebug() << "Received data from client: " << data; }); }); ``` 客户端代码: ```cpp QTcpSocket socket; socket.connectToHost("127.0.0.1", 1234); // 连接到服务器的IP地址和端口号 if (socket.waitForConnected()) { socket.write("Hello server"); // 发送数据到服务器 socket.waitForBytesWritten(); } ``` 以上代码只是一个简单的示例,实际应用中可能需要处理更复杂的数据交互和错误处理。需要注意的是,QTcpSocket和QTcpServer类都继承自QObject类,因此可以使用信号与槽机制来处理连接、数据接收等事件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值