QT TCP服务器

客户端:

功能:

连接:获取ip地址和端口号,并连接   取消:关闭窗口

工程文件加上

QT=+=core gui network

相关类与函数

QTcpSocket类:(需要被包含)

connectToHost()  连接。参数:QHostAdress地址对象(可用QString初始化),端口号(16位短整型)(QString自带进制转换,如ip.toshort)

连接成功后会发出一个信号:&QTcpSocket::connected

连接异常也会发出一个信号:&QTcpSocket::disconnected

peerAddress();获取客户端地址

peerAddress的子函数toString():将其转化位字符串

peerPort():获取客户端端口号(并非服务器端口)

write():参数:QByteArray ,可用append拼接,发送后会出现&QTcpSocket::readyread信号

QHostAddress类:(需要被包含)

其他函数:

(QTcpSocket * )sender();获取信号的发送者并强制转为QTcpSocket指针

服务器:

相关类与函数:

QTcpServer类:

listen():监听网卡,参数QHostAdress::AnyIPv4,端口号

如果有信号,会发出QTcpServer::newConnection信号

nextPendingConnection() 建立TCP连接,返回QTcpSocket类型

实现服务器与客户端连接

在widget构造函数中监听网卡ip,等待请求,收到信号后与客户端建立连接

注意,必须使用127开头的地址

127.0.0.1 地址称为本地回环地址,是一种特殊的网络地址,用于让单独的计算机进行自我回路测试和通信。 这个地址在 IP 协议中被定义为环回地址。 在网络设备中,网络接口上的 127.0.0.1 地址本质上是本机对自己的网络地址。

通信

打开其他窗口:新建qt->设计师...,在客户端创建新的窗口类chat

this->hide()隐藏窗口

创建新窗口对象时要用堆空间创建,也即是指针形式,这样申请的内存不会被销毁,

widget在连接成功后隐藏当前窗口,并打开新窗口chat,与打开widget窗口类似

         chat *k=new chat(SOCKET);
         k->show();

要将socket信息传到新窗口中,所以类chat中要有参数,并在chat构造函数中初始化

QTcpSocket *s

在新窗口中,使用socket中的write发送信息,参数是QByteArray类型

在服务器中连接后再connect一个新的信号与曹:

&QTcpSocket::readyRead
&Widget::data_resslot

在槽函数中要注意变量的范围,如果QTcpSocket指针是内部变量,则需要使用

(QTcpSocket*)sender();

将其转化为QTcpSocket类型指针,再用readAll读取所有发送的数据。

服务器代码:

chat.h

#ifndef CHAT_H
#define CHAT_H

#include <QWidget>
#include <QTcpSocket>


namespace Ui {
class chat;
}

class chat : public QWidget
{
    Q_OBJECT

public:
    explicit chat(QTcpSocket *s,QWidget *parent = nullptr);
    ~chat();

private slots:
    void on_clearButton_clicked();

    void on_sendButton_2_clicked();

private:
    Ui::chat *ui;
    QTcpSocket *SOCKET;
};

#endif // CHAT_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>
#include <QDebug>
#include <QMessageBox>
#include <chat.h>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


private slots:
    void on_cancelButton_2_clicked();

    void on_connectButton_clicked();

    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QTcpSocket *SOCKET;
};
#endif // WIDGET_H

chat.cpp

#include "chat.h"
#include "ui_chat.h"

chat::chat(QTcpSocket *s,QWidget *parent) :
    QWidget(parent),
    ui(new Ui::chat)
{
    ui->setupUi(this);
    SOCKET=s;
}

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

void chat::on_clearButton_clicked()
{
    ui->lineEdit->clear();
}

void chat::on_sendButton_2_clicked()
{
    QString text1=ui->lineEdit->text();
    QByteArray ba;
    ba.append(text1);
    //write只能发送QByteArray类型数据
    SOCKET->write(ba);
}

widget.cpp

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

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    SOCKET=new QTcpSocket;
    //成功/异常警告
    connect(SOCKET,&QTcpSocket::connected,[this]()
    {
         QMessageBox::information(this,"提示","连接成功");
         this->hide();
         chat *k=new chat(SOCKET);
         k->show();
    });
    connect(SOCKET,&QTcpSocket::disconnected,[this]()
    {
         QMessageBox::warning(this,"警告","连接异常");
    });

}

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


void Widget::on_cancelButton_2_clicked()
{
    this->close();
}

void Widget::on_connectButton_clicked()
{
    //获取ip与端口号
    QString com1=ui->COMlineEdit_2->text();
    QString ip1=ui->IPlineEdit->text();
    if(com1.isEmpty()||ip1.isEmpty())
    {
        QMessageBox::warning(this,"警告","请输入ip地址和端口号");
    }
    //开始连接
    SOCKET->abort();
    SOCKET->connectToHost(QHostAddress(ip1),com1.toShort());
}

void Widget::on_pushButton_clicked()
{
    qDebug()<<"disconnect";
    SOCKET->disconnectFromHost();
}

服务器代码:

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QDebug>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QMessageBox>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
#define TCPCOM 8000



class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void serverslot();
    void on_check_clicked();
    void data_resslot();
private:
    Ui::Widget *ui;
    QTcpServer *SERVER;
};
#endif // WIDGET_H

widget.cpp

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

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    SERVER=new QTcpServer;
    SERVER->listen(QHostAddress::Any,TCPCOM);
    qDebug()<<TCPCOM;
    connect(SERVER,&QTcpServer::newConnection,this,&Widget::serverslot);
}

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

void Widget::serverslot()
{
    QTcpSocket *SOCKET1;
    SOCKET1=SERVER->nextPendingConnection();
    QHostAddress ip1=SOCKET1->peerAddress();
    quint16 com1=SOCKET1->peerPort();
    ui->comlineEdit->setText(QString::number(com1));
    ui->iplineEdit_2->setText(ip1.toString());
    QMessageBox::information(this,"提示","连接成功");
    connect(SOCKET1,&QTcpSocket::readyRead,this,&Widget::data_resslot);
}




void Widget::on_check_clicked()
{
    if(SERVER->isListening())
    {
            qDebug()<<"IS LISTENING";
    }

}
void Widget::data_resslot()
{
    QTcpSocket *Socket=(QTcpSocket*)sender();
    ui->datalineEdit->setText(Socket->readAll());

}

结果:

多线程

在服务器中启用多线程,即可接收多个客户端的连接。

相关类与函数

在文件中添加c++类,在继承中继承QThread,添加后多了.h和.cpp文件

QThread类,需要包含

start()打开线程

虚函数run():在run里连接信号与槽,线程处理函数

自定义信号

在类中定义,和private同级,在信号传递时可以附加参数

signals:

void sendtowidget(QByteArray ba);

在需要发出信号的地方加上即可,最后在widget中连接信号与槽

QByteArray ba=socket->readall();
emit sendtowidget(ba);

### 如何在 Qt 中实现 TCP 服务器 #### 头文件 `TcpServer.h` 定义 头文件定义了一个名为 `TcpServer` 的类,该类继承自 `QObject` 并实现了必要的信号和槽函数来处理客户端连接、数据读取以及断开事件[^1]。 ```cpp #ifndef TCPSERVER_H #define TCPSERVER_H #include <QObject> #include <QTcpServer> #include <QTcpSocket> class TcpServer : public QObject { Q_OBJECT public: explicit TcpServer(QObject *parent = nullptr); signals: public slots: void startServer(); void newClientConnection(); void readData(); void clientDisconnected(); private: QTcpServer *tcpServer; QList<QTcpSocket *> clients; }; #endif // TCPSERVER_H ``` --- #### 源文件 `TcpServer.cpp` 实现 源文件中包含了具体的逻辑实现,包括启动服务器、接收新连接、读取数据以及处理客户端断开等功能[^2]。 ```cpp #include "TcpServer.h" #include <QDebug> TcpServer::TcpServer(QObject *parent) : QObject(parent), tcpServer(new QTcpServer(this)) { } void TcpServer::startServer() { if (!tcpServer->listen(QHostAddress::Any, 12345)) { qDebug() << "Failed to start server:" << tcpServer->errorString(); return; } connect(tcpServer, &QTcpServer::newConnection, this, &TcpServer::newClientConnection); qDebug() << "Server started on port" << tcpServer->serverPort(); } void TcpServer::newClientConnection() { while (tcpServer->hasPendingConnections()) { QTcpSocket *clientSocket = tcpServer->nextPendingConnection(); clients.append(clientSocket); connect(clientSocket, &QTcpSocket::readyRead, this, &TcpServer::readData); connect(clientSocket, &QTcpSocket::disconnected, this, &TcpServer::clientDisconnected); qDebug() << "New client connected:" << clientSocket->peerAddress().toString(); } } void TcpServer::readData() { QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (socket) { QString data = socket->readAll(); qDebug() << "Received from client:" << data; foreach (QTcpSocket *client, clients) { if (client != socket && client->state() == QAbstractSocket::ConnectedState) { client->write(data); // 转发消息给其他客户端 } } } } void TcpServer::clientDisconnected() { QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (socket) { clients.removeAll(socket); socket->deleteLater(); qDebug() << "Client disconnected:" << socket->peerAddress().toString(); } } ``` --- #### 使用说明 为了运行上述代码并创建一个功能完整的 TCP 服务器,需按照以下方式操作: 1. **初始化对象**: 创建 `TcpServer` 类的对象实例。 2. **调用方法**: 调用 `startServer()` 方法以启动监听指定端口的服务。 3. **处理事件**: 当有新的客户端连接时触发 `newClientConnection()`;当接收到数据时触发 `readData()`;当客户端断开时触发 `clientDisconnected()`。 示例主程序如下所示: ```cpp #include <QCoreApplication> #include "TcpServer.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TcpServer server; server.startServer(); return a.exec(); } ``` --- #### 测试效果 通过以上代码可以构建一个基本的 TCP 服务器。它能够接受多个客户端的同时连接,并支持广播模式下的通信(即向所有已连接的客户端转发任意一条消息)。此设计适用于聊天室或其他多用户实时交互场景[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值