socket通信(UDP、TCP)的Qt实现

socket通信原理

什么是Socket?

Socket的中文翻译过来就是“套接字”。套接字是什么,我们先来看看它的英文含义:插座。

Socket就像一个电话插座,负责连通两端的电话,进行点对点通信,让电话可以进行通信,端口就像插座上的孔,端口不能同时被其他进程占用。而我们建立连接就像把插头插在这个插座上,创建一个Socket实例开始监听后,这个电话插座就时刻监听着消息的传入,谁拨通我这个“IP地址和端口”,我就接通谁。

实际上,Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。Socket起源于UNIX,在Unix一切皆文件的思想下,进程间通信就被冠名为文件描述符(file desciptor),Socket是一种“打开—读/写—关闭”模式的实现,服务器和客户端各自维护一个“文件”,在建立连接打开后,可以向文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。
socket通信

Socket通信过程

Socket保证了不同计算机之间的通信,也就是网络通信。对于网站,通信模型是服务器与客户端之间的通信。两端都建立了一个Socket对象,然后通过Socket对象对数据进行传输。通常服务器处于一个无限循环,等待客户端的连接。

tip:服务器与客户端
UDP通信

服务器:发送数据
客户端:接收数据

TCP通信

服务器:等待连接和收发数据
客户端:主动连接和收发数据

UDP通信过程

无需建立连接,服务器只管发;客户端只管收,挨个取出内存中数据报。
UDP通信

socket通信(UDP)——Qt实现

0.工程文件*.pro里面加入网络模块;

QT     += network
服务器(发送数据):

1.创建socket

#include  <QUdpSocket>

m_socket = new QUdpSocket(this)

2.发送数据

m_socket->writeDatagram(sendMsg.toLatin1(), sendMsg.length(),
                                         QHostAddress::Broadcast, port)
客户端(接收数据):

1.创建socket

#include  <QUdpSocket>

m_socket = new QUdpSocket(this)

2.绑定端口

isBind = m_socket->bind(m_port);
if(!isBind)
{
    QMessageBox::information(this, "error", "not bind success!");
    break;
}

3.有则接收(readDatagram:接收数据报)

connect(m_socket, &QUdpSocket::readyRead, this, [=]()
{

    while(m_socket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(m_socket->pendingDatagramSize());
        m_socket->readDatagram(datagram.data(), datagram.size());
        QString msg = datagram.data();
        ui->record->append("服务器:" + msg);
    }

});

TCP通信过程

需要先建立连接,服务器和客户端收发都会得到确认,传输完毕需要断开连接。

socket通信(TCP)——Qt实现

使用 Qt 提供的类进行基于 TCP 的套接字通信需要用到两个类:

QTcpServer:服务器类,用于监听客户端连接以及和客户端建立连接。
QTcpSocket:通信的套接字类,客户端、服务器端都需要使用。

0.工程文件*.pro里面加入网络模块;

QT     += network
服务器:

1.创建 QTcpServer 对象

#include  <QTcpServer>
#include  <QTcpSocket>
m_server = new QTcpServer(this);

2.设置服务器监听

m_server->listen(QHostAddress::Any, port);

3.检测是否有新的客户端连接,接收消息(readAll)

connect(m_server, &QTcpServer::newConnection, this, [=]()
{
    m_socket = m_server->nextPendingConnection();
    ui->record->append("成功和客户端建立了新的连接...");
    // 检测是否有客户端数据
    connect(m_socket, &QTcpSocket::readyRead, this, [=]()
    {
        // 接收数据
        QString recvMsg = m_tcp->readAll();
        ui->record->append("客户端Say: " + recvMsg);
    });
    // 客户端断开了连接
    connect(m_socket, &QTcpSocket::disconnected, this, [=]()
    {
        ui->record->append("客户端已经断开了连接...");
        m_tcp->deleteLater();
    });
});

4.点击发送数据按钮(write)

void MainWindow::on_sendMsg_clicked()
{
    QString sendMsg = ui->msg->toPlainText();
    m_socket->write(sendMsg.toUtf8());
    ui->record->append("服务器Say: " + sendMsg);
    ui->msg->clear();
}
客户端:

1.创建通信的套接字对象

#include  <QTcpSocket>
m_socket = new QTcpSocket(this);

2.连接服务器

m_socket->connectToHost(QHostAddress(ip), port);

3.检测是否和服务器是否连接成功了

connect(m_socket, &QTcpSocket::connected, this, [=]()
{
    ui->record->append("恭喜, 连接服务器成功!!!");
});

4.检测服务器是否回复了数据,有则接收

connect(m_socket, &QTcpSocket::readyRead, [=]()
{
    // 接收服务器发送的数据
    QByteArray recvMsg = m_tcp->readAll();
    ui->record->append("服务器Say: " + recvMsg);
});

5.检测服务器是否和客户端断开了连接

connect(m_socket, &QTcpSocket::disconnected, this, [=]()
{
    ui->record->append("服务器已经断开了连接, ...");
});

6.发送数据

QString sendMsg = ui->msg->toPlainText();
m_socket->write(sendMsg.toUtf8());

7.断开连接

m_tcp->close();

参考链接:
https://subingwen.cn/qt/socket-tcp/#3-1-2-%E4%BB%A3%E7%A0%81%E7%89%87%E6%AE%B5

  • 5
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt实现TCPUDP双线程,可以使用QtQTcpSocket和QUdpSocket类来实现。 首先,在服务器端,你可以创建一个QTcpServer对象来监听和接受TCP连接,并在每个新的连接上创建一个QTcpSocket对象来处理通信。同时,你也可以创建一个QUdpSocket对象来处理UDP通信。 以下是一个简单的示例代码,展示了如何在服务器端使用TCPUDP双线程: ```cpp // server.h #ifndef SERVER_H #define SERVER_H #include <QMainWindow> #include <QTcpServer> #include <QTcpSocket> #include <QUdpSocket> namespace Ui { class Server; } class Server : public QMainWindow { Q_OBJECT public: Server(QWidget *parent = nullptr); ~Server(); private slots: void on_pushButton_listen_clicked(); // TCP侦听 void server_new_connect(); // 创建新连接 void socket_read_data(); // TCP读取缓冲区数据 void read_data(); // UDP读取缓冲区数据 void on_comboBox_currentIndexChanged(); // 界面转换 private: Ui::Server *ui; QUdpSocket *uServer; // UDP套接字对象 QTcpServer *mServer; QTcpSocket *mSocket; // TCP套接字对象 int i1, i2; int j1, j2; }; #endif // SERVER_H ``` ```cpp // server.cpp #include "server.h" #include <QApplication> #include <QTimer> Server::Server(QWidget *parent) : QMainWindow(parent) , ui(new Ui::Server) { ui->setupUi(this); // 创建QTcpServer对象 mServer = new QTcpServer(this); // 连接新的连接信号和槽函数 connect(mServer, &QTcpServer::newConnection, this, &Server::server_new_connect); // 创建QUdpSocket对象 uServer = new QUdpSocket(this); // 连接readyRead信号和槽函数 connect(uServer, &QUdpSocket::readyRead, this, &Server::read_data); } Server::~Server() { delete ui; } void Server::on_pushButton_listen_clicked() { // 开始监听指定的端口 if (mServer->listen(QHostAddress::Any, ui->lineEdit_port->text().toInt())) { ui->textEdit_info->append("Server is listening..."); } else { ui->textEdit_info->append("Failed to start server!"); } } void Server::server_new_connect() { // 获取新的连接 mSocket = mServer->nextPendingConnection(); // 连接readyRead信号和槽函数 connect(mSocket, &QTcpSocket::readyRead, this, &Server::socket_read_data); // 输出连接信息 ui->textEdit_info->append("New client connected!"); } void Server::socket_read_data() { // 读取缓冲区数据 QByteArray data = mSocket->readAll(); // 处理数据 // ... } void Server::read_data() { // 读取缓冲区数据 QByteArray data = uServer->readAll(); // 处理数据 // ... } void Server::on_comboBox_currentIndexChanged() { // 界面转换 // ... } ``` 在上述示例中,`Server`类继承自`QMainWindow`,在构造函数中创建了`QTcpServer`和`QUdpSocket`对象,并连接了相应的信号和槽函数。其中,`on_pushButton_listen_clicked`槽函数用于开始监听指定的端口,`server_new_connect`槽函数用于处理新的TCP连接,`socket_read_data`槽函数用于读取TCP缓冲区数据,`read_data`槽函数用于读取UDP缓冲区数据,`on_comboBox_currentIndexChanged`槽函数用于界面转换。 请注意,以上代码只是一个简单示例,你可以根据自己的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值