Qt中Tcp通信

        Tcp通信一般分为客户端和服务器端。

        对于客户端,Qt提供QTcpSocket类进行处理,客户端主要功能有连接服务器,发送数据,接收数据等。

        示例代码:

//创建套接字
QTcpSocket *tcpSocket;
tcpSocket = new QTcpSocket;
//连接信号和处理槽
connect(tcpSocket, &QTcpSocket::connected, [](){ qDebug() << "Connected successfully !"; });
connect(tcpSocket, &QTcpSocket::disconnected, [](){ qDebug() << "Disconnected!"; });
connect(tcpSocket, &QTcpSocket::stateChanged, [](QAbstractSocket::SocketState socketState){ qDebug() << "SocketState changed: " << socketState;
});
connect(tcpSocket, &QTcpSocket::readyRead,this, &MyThread::slotReadData);
//连接服务器
tcpSocket->connectToHost("192.168.2.194", 5002);
//等待连接成功
tcpSocket->waitForConnected(1000);
//发送数据
QString command = "00 01 02 03 04 05 06 07 08";
QByteArray array = QByteArray::fromHex(command.toLatin1());
tcpSocket->write(array);
tcpSocket->waitForBytesWritten();
tcpSocket->flush();
//接收数据
while(tcpSocket->bytesAvailable()>0){
    QByteArray datagram;
    datagram.resize(tcpSocket->bytesAvailable());
    tcpSocket->read(datagram.data(),datagram.size());
    QString msg = datagram.data();
    contentListWidget->addItem(msg.left(datagram.size()));
}
//断开连接
tcpSocket->disconnectFromHost();
tcpSocket->waitForDisconnected();

        对于服务端,Qt提供了QTcpServer类来帮助我们处理。但是一个服务器端对应很多的客户端,为了方便处理,我们一般继承QTcpServer创建Server子类。重写incomingConnection(int socketDescriptor)函数。子类Server中可以添加QList<QTcpSocket*>类型变量,将所有连接到服务器上的客户端存储下来。在构造函数中,需要添加listen进行监听是否有客户端连接。当有连接来的时候,发出信号incomingConnection(int socketDescriptor),在接收到incomingConnection信号的槽函数中对客户端socket进行处理,可以使用多线程进行处理,对每一个客户端采用一个线程处理。

        服务端示例代码:

//server.h
#include <QTcpServer>
#include <QObject>
#include "tcpclientsocket.h"

class Server : public QTcpServer
{
    Q_OBJECT
public:
    Server(QObject *parent = 0,int port = 0);
    QList<TcpClientSocket*> tcpClientSocketList;

signals:
    void updateServer(QString ,int);

public slots:
    void updateClients(QString ,int);
    void slotDisconnected(int);

protected:
    void incomingConnection(int socketDescriptor);

};

//server.cpp
Server::Server(QObject *parent, int port) : QTcpServer(parent)
{
    listen(QHostAddress::Any,port);
}

void Server::incomingConnection(int socketDescriptor){
    TcpClientSocket *tcpClientSocket = new TcpClientSocket(this);
    connect(tcpClientSocket,&TcpClientSocket::updateClients,this,&Server::updateClients);
    connect(tcpClientSocket,&TcpClientSocket::disconnected,this,&Server::slotDisconnected);
    tcpClientSocket->setSocketDescriptor(socketDescriptor);
    tcpClientSocketList.append(tcpClientSocket);
}

void Server::updateClients(QString msg,int length){
    emit updateServer(msg,length);
    for(int i=0; i<tcpClientSocketList.size(); i++){
        QTcpSocket *item = tcpClientSocketList.at(i);
        if(item->write(msg.toLatin1(),length)!=length){
            continue;
        }
    }
}

void Server::slotDisconnected(int descriptor){
    for(int i=0; i<tcpClientSocketList.size();i++){
        QTcpSocket *item = tcpClientSocketList.at(i);
        if(item->socketDescriptor() == descriptor){
            tcpClientSocketList.removeAt(i);
            return;
        }
    }
    return;
}

        对于服务端的QTcpSocket,主要需要处理接收到客户端的信息,并将该信息传递给所有连接该服务器的客户端(根据需求设计)。示例代码如下:

//tcpclientsocket.h
#include <QTcpSocket>
#include <QObject>

class TcpClientSocket : public QTcpSocket
{
    Q_OBJECT
public:
    TcpClientSocket(QObject *parent = 0);

signals:
    void updateClients(QString, int);
    void disconnected(int);

protected slots:
    void dataReceived();
    void slotDisconnected();

};
//tcpclientsocket.cpp
TcpClientSocket::TcpClientSocket(QObject *parent)
{
    connect(this,&QTcpSocket::readyRead,this,&TcpClientSocket::dataReceived);
    connect(this,&TcpClientSocket::disconnected,this,&TcpClientSocket::slotDisconnected);
}

void TcpClientSocket::dataReceived(){
    while(bytesAvailable()>0){
        int length = bytesAvailable();
        char buf[1024];
        read(buf,length);
        QString msg = buf;
        emit updateClients(msg,length);
    }
}

void TcpClientSocket::slotDisconnected(){
    emit disconnected(this->socketDescriptor());
}

        如果客户端用多线程处理,示例处理代码如下:

//调用
WorkerThread* thread = new WorkerThread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));thread->start();
//run()函数
QTcpSocket tcpSocket;
if(!tcpSocket.setSocketDescriptor(socketDesc)) return;
QString info = QString("[%0:%1]").arg(tcpSocket.peerAddress().toString()).arg(tcpSocket.peerPort());
qDebug() << info << " connected.";
while (true){
     if(tcpSocket.error() == QAbstractSocket::RemoteHostClosedError)
        break;
     if(tcpSocket.waitForReadyRead(0))
     {
        QByteArray data = tcpSocket.readAll();
        if(strncmp(data.toStdString().c_str(), "quit", 4) == 0)
            break;
        tcpSocket.write(data);
        tcpSocket.waitForBytesWritten();
     }
}
tcpSocket.close();
qDebug() << info << " disconnected.";

  • 3
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值