QT示例:基于TCP 点对多Socket通讯(server,clients)

本文介绍如何使用QT实现TCP点对多的Socket通讯,重点讲解服务器如何处理多个客户端连接,包括两种处理策略:重写`incomingConnection()`获取SocketDescriptor,或者使用`QTcpSocket`的`peerAddress()`和`peerPort()`获取客户端标识。示例代码涵盖了服务器和客户端的创建及配置。
摘要由CSDN通过智能技术生成

QT示例:基于TCP 点对多通讯(server,clients)

下载:基于TCP 点对多Socket通讯

一、服务器server

因为对于客户端来说,只能连接一个服务器。而对于服务器来说,它是面向多连接的,如何协调处理多客户端连接就显得尤为重要。

  • 注意问题:
    每个新加入的客户端,服务器给其分配一个SocketDescriptor后,就会emit newConnection()信号,但分配好的SocketDecriptor并没有通过newConnection()信号传递,所以用户得不到这个客户端标识SocketDescriptor。同样的,每当服务器收到新的消息时,客户端会emit readReady()信号,然而readReady()信号也没有传递SocketDescriptor, 这样的话,服务器端即使接收到消息,也不知道这个消息是从哪个客户端发出的。
  • 解决的方法:
  1. 通过重写==[virtual protected] void QTcpServer::incomingConnection(qintptr socketDescriptor)==,获取soketDescriptor。自定义TcpClient类继承QTcpSocket,并将获得的soketDescriptor作为类成员。 这个方法的优点是:可以获取到soketDescriptor,灵活性高。缺点是:需要重写函数、自定义类。
  2. 在newConnection()信号对应的槽函数中,通过QTcpSocket *QTcpServer::nextPendingConnection()函数获取 新连接的客户端:Returns the next pending connection as a connected QTcpSocket object. 虽然仍然得不到soketDescriptor,**但可以通过QTcpSocket类的peerAddress()和peerPort()成员函数获取客户端的IP和端口号,同样是唯一标识。 **优点:无需重写函数和自定义类,代码简洁。缺点:无法获得SocketDecriptor,灵活性差。

本文示例为第二种方法:
1).pro 添加:

QT       += network

2)主函数 main.cpp 添加:

#include "mytcpserver.h"
#include <QApplication>

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

    return a.exec();
}

3)MyTcpServer.h 添加:

#include "mytcpserver.h"
#include "ui_mytcpserver.h"

MyTcpServer::MyTcpServer(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MyTcpServer)
{
   
    ui->setupUi(this);
    //  一 、创建QTcpSever对象;
    tcpServer = new QTcpServer(this);
    ui->edtIP->setText(QNetworkInterface().allAddresses().at(1).toString());   //获取本地IP
    ui->btnConnect->setEnabled(true);
    ui->btnSend->setEnabled(false);
    // 设置默认按钮样式
	ui->btnConnect->setStyleSheet("");

    connect(tcpServer, &QTcpServer::newConnection, this, &MyTcpServer::NewConnectionSlot);
}

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

// 二、监听--断开
void MyTcpServer::on_btnConnect_clicked()
{
   
    if(ui->btnConnect->text()=="监听")
    {
   
        bool ok = tcpServer->listen(QHostAddress::Any, ui->edtPort->text().toInt());
        if(ok)
        {
   
            ui->btnConnect->setText("断开");
            ui->btnConnect->setStyleSheet("color: red;");
            ui->btnSend->setEnabled(true);
        }
    }
    else
    {
   
        for(int i=0; i<tcpClient.length(); i++) // 断开所有连接
        
  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中,可以使用QTcpSocketQTcpServer类来实现TCP通信。为了实现多线程通信,我们可以使用QtQThread类。 下面是一个简单的示例代码,它演示了如何使用Qt实现TCP多线程上位机通信: ```cpp // server.h #ifndef SERVER_H #define SERVER_H #include <QObject> #include <QTcpServer> #include <QTcpSocket> class Server : public QObject { Q_OBJECT public: explicit Server(QObject *parent = nullptr); void startServer(); void stopServer(); signals: void newMessage(QString message); private slots: void acceptConnection(); void readData(); void displayError(QAbstractSocket::SocketError socketError); private: QTcpServer *m_server; QList<QTcpSocket *> m_clients; }; #endif // SERVER_H ``` ```cpp // server.cpp #include "server.h" Server::Server(QObject *parent) : QObject(parent), m_server(nullptr) { m_server = new QTcpServer(this); connect(m_server, SIGNAL(newConnection()), this, SLOT(acceptConnection())); } void Server::startServer() { if (!m_server->listen(QHostAddress::Any, 1234)) { qDebug() << "Could not start server"; return; } qDebug() << "Server started!"; } void Server::stopServer() { m_server->close(); foreach (QTcpSocket *client, m_clients) { client->close(); } } void Server::acceptConnection() { QTcpSocket *client = m_server->nextPendingConnection(); connect(client, SIGNAL(readyRead()), this, SLOT(readData())); connect(client, SIGNAL(disconnected()), client, SLOT(deleteLater())); m_clients.append(client); qDebug() << "New client connected!"; } void Server::readData() { QTcpSocket *client = qobject_cast<QTcpSocket *>(sender()); if (!client) return; QString message = QString::fromUtf8(client->readAll()); emit newMessage(message); } void Server::displayError(QAbstractSocket::SocketError socketError) { qDebug() << "Socket error:" << socketError; } ``` ```cpp // client.h #ifndef CLIENT_H #define CLIENT_H #include <QObject> #include <QTcpSocket> class Client : public QObject { Q_OBJECT public: explicit Client(QObject *parent = nullptr); public slots: void connectToServer(QString host, int port); void disconnectFromServer(); void sendMessage(QString message); signals: void connected(); void disconnected(); void newMessage(QString message); private slots: void readData(); void displayError(QAbstractSocket::SocketError socketError); private: QTcpSocket *m_socket; }; #endif // CLIENT_H ``` ```cpp // client.cpp #include "client.h" Client::Client(QObject *parent) : QObject(parent), m_socket(nullptr) { m_socket = new QTcpSocket(this); connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); connect(m_socket, SIGNAL(connected()), this, SIGNAL(connected())); connect(m_socket, SIGNAL(disconnected()), this, SIGNAL(disconnected())); } void Client::connectToServer(QString host, int port) { m_socket->connectToHost(host, port); } void Client::disconnectFromServer() { m_socket->close(); } void Client::sendMessage(QString message) { m_socket->write(message.toUtf8()); } void Client::readData() { QString message = QString::fromUtf8(m_socket->readAll()); emit newMessage(message); } void Client::displayError(QAbstractSocket::SocketError socketError) { qDebug() << "Socket error:" << socketError; } ``` 在这个示例中,Server类和Client类分别表示服务器和客户端。Server类在开始时会创建一个QTcpServer对象并开始监听来自任何地址的连接请求。每当一个新的连接请求到达时,Server类会创建一个QTcpSocket对象来处理该连接。然后,Server类将客户端的QTcpSocket对象添加到一个列表中,以便在以后可以轻松地访问所有客户端。 Client类在连接到服务器时会创建一个QTcpSocket对象,并尝试与指定的主机和端口号建立连接。一旦连接成功,客户端就可以发送消息到服务器。每当客户端收到服务器的消息时,它将发出newMessage信号。 你可以通过创建QThread类的子类来实现多线程通信。在run()方法中,可以使用Server对象或Client对象来处理通信
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值