QTcpSocket 套接字收发结构体

客户端:

dialogclient.h

#ifndef DIALOGCLIENT_H
#define DIALOGCLIENT_H

#include <QDialog>
#include <QtNetwork>

namespace Ui {
class DialogClient;
}


//结构体
struct NetData
{
    unsigned int length;
    unsigned int n1;
    double d1;
    double d2;
    char name[32];  //这里数组可以,注意如果是指针指向堆空间,堆里数据要自己copy
};


class DialogClient : public QDialog
{
    Q_OBJECT

public:
    explicit DialogClient(QWidget *parent = 0);
    ~DialogClient();

private slots:
    void on_pushButtonConnect_clicked();

    //连接成功
    void OnSuccConnect();
    //接收数据
    void ReadStructDataAndShow();


private:
    Ui::DialogClient *ui;
    QTcpSocket *m_pTCPClient;
};

#endif // DIALOGCLIENT_H

dialogclient.cpp

#include "dialogclient.h"
#include "ui_dialogclient.h"
#include <QIntValidator>
#include <QHostAddress>
#include <QMessageBox>
#include <QDebug>

DialogClient::DialogClient(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogClient)
{
    ui->setupUi(this);

    //端口验证
    QIntValidator *vali = new QIntValidator();
    vali->setRange(0, 65535);
    ui->lineEditPort->setValidator(vali);
    //
    ui->lineEditPort->setText("2000");
    ui->lineEditIP->setText("127.0.0.1");

    this->setLayout(ui->mainLayout);

    //创建客户端
    m_pTCPClient = new QTcpSocket();
    //关联信号
    connect(m_pTCPClient, SIGNAL(connected()), this, SLOT(OnSuccConnect()));
    connect(m_pTCPClient, SIGNAL(readyRead()), this, SLOT(ReadStructDataAndShow()));
}

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

void DialogClient::on_pushButtonConnect_clicked()
{
    int nPort = ui->lineEditPort->text().toInt();
    QHostAddress address;
    bool bres = address.setAddress(ui->lineEditIP->text());
    //如果IP出错
    if( ! bres )
    {
        QMessageBox::warning(this, tr("IP address error"), tr("IP address is not correct!"));
        return;
    }
    //开始连接
    m_pTCPClient->connectToHost(address, nPort);

}

void DialogClient::OnSuccConnect()
{
    QMessageBox::information(this, tr("Connected"), tr("Connect successed."));
}

void DialogClient::ReadStructDataAndShow()
{
    QString strMsg;
    QByteArray dataArray = m_pTCPClient->readAll();
    if(dataArray.length() != sizeof(NetData))
    {
        //长度不对
        strMsg = tr("Receive error, struct length is %1 B, recv length is %2 B")
                .arg(sizeof(NetData)).arg(dataArray.length());

        qDebug()<<strMsg;
        //
        return;
    }
    //接收长度正确
    const NetData* pData = (NetData*)(dataArray.data());
    //显示
    QString strShow = tr("NetData: \r\n");
    strShow += tr("Length = %1\r\n").arg(pData->length);
    strShow += tr("n1 = %1\r\n").arg(pData->n1);
    strShow += tr("d1 = %1\r\n").arg(pData->d1);
    strShow += tr("d2 = %1\r\n").arg(pData->d2);
    strShow += tr("name = %1\r\n").arg(pData->name);
    //显示
    ui->labelShow->setText(strShow);

}

服务端:

dialogserver.h

#ifndef DIALOGSRV_H
#define DIALOGSRV_H

#include <QDialog>
#include <QtNetwork>
#include <QStringList>
#include <QList>
#include "clientjobs.h"

namespace Ui {
class DialogSrv;
}

//结构体
struct NetData
{
    unsigned int length;
    unsigned int n1;
    double d1;
    double d2;
    char name[32];  //这里数组可以,注意如果是指针指向堆空间,堆里数据要自己copy
};


class DialogSrv : public QDialog
{
    Q_OBJECT

public:
    explicit DialogSrv(QWidget *parent = 0);
    ~DialogSrv();

private slots:
    void on_pushButtonListen_clicked();
    //两个信号的槽函数
    void onNewConnection();
    //
    void DeleteOneClient(QString strIPAndPort);


    void on_pushButtonStop_clicked();

    void on_pushButtonSend_clicked();

private:
    Ui::DialogSrv *ui;
    //server
    QTcpServer *m_pTCPSrv;

    //保存客户列表
    QStringList m_listIPAndPorts;  //IP_Port
    QList<ClientJobs*> m_listClients;//客户端


};

#endif // DIALOGSRV_H

dialogserver.cpp

#include "dialogsrv.h"
#include "ui_dialogsrv.h"
#include <QMessageBox>
#include <QIntValidator>    //验证端口号
#include <QHostAddress>
#include <QByteArray>
#include <QDebug>

DialogSrv::DialogSrv(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogSrv)
{
    ui->setupUi(this);

    QIntValidator *vali = new QIntValidator();
    vali->setRange(0, 65535);
    ui->lineEditPort->setValidator(vali);   //限制端口范围
    ui->lineEditPort->setText("2000");  //默认监听端口
    this->setLayout(ui->mainLayout);    //设置界面排布

    //构建TCP服务器
    m_pTCPSrv = new QTcpServer(this);
    //关联成功接收连接的信号
    connect(m_pTCPSrv, SIGNAL(newConnection()), this, SLOT(onNewConnection()));

}

DialogSrv::~DialogSrv()
{
    delete m_pTCPSrv;   m_pTCPSrv = NULL;
    delete ui;
}

void DialogSrv::on_pushButtonListen_clicked()
{
    if( m_pTCPSrv->isListening() )
    {
        //已经在监听,啥都不干
        return;
    }
    //需要开启监听
    //获取端口
    int nPort = ui->lineEditPort->text().toInt();

    bool bres = m_pTCPSrv->listen(QHostAddress::Any, nPort);
    if(bres)
    {
        //成功
        QMessageBox::information(this, tr("Listen"), tr("Listen successed."));
        return;
    }
    else
    {
        //失败
        QMessageBox::warning(this, tr("Listen"), tr("Listen failed."));
        return;
    }
}

void DialogSrv::onNewConnection()
{
    //接收新连接
    QTcpSocket *sockclient = m_pTCPSrv->nextPendingConnection();
    //获取远端IP和端口
    QString strIPAndPort = sockclient->peerAddress().toString() + tr(" __ %1").arg(sockclient->peerPort());
    //添加到列表
    ui->listWidget->addItem(strIPAndPort);
    //构建客户端对象
    ClientJobs *pClientJob = new ClientJobs(this, sockclient, strIPAndPort);
    //IP-port列表
    m_listIPAndPorts.append(strIPAndPort);
    //客户端列表
    m_listClients.append(pClientJob);
    //
    connect(pClientJob, SIGNAL(CallMainWindowDeleteClient(QString)), this, SLOT(DeleteOneClient(QString)));

}


void DialogSrv::on_pushButtonStop_clicked()
{
    if(m_pTCPSrv->isListening())
    {
        m_pTCPSrv->close();
    }
    else
    {
        return;
    }

}


//发送测试数据
void DialogSrv::on_pushButtonSend_clicked()
{
    //判断有无客户端接入
    if( m_listClients.count() < 1 )
    {
        return;
    }
    //判断选择的是哪个客户端
    int nIndex = ui->listWidget->currentRow();
    if(nIndex < 0)
    {
        //没选择客户端发送
        return;
    }
    //使用向nIndex号客户端发包
    //构造结构体
    NetData ssData;
    //填充数据
    ssData.length = sizeof(NetData);
    ssData.n1 = 1;
    ssData.d1 = 2.0;
    ssData.d2 = 4.0;
    char name[32] = "Say Hello.";
    strncpy(ssData.name, name, 32);
    //转为QByteArray发送
    QByteArray dataArray = QByteArray::fromRawData((char*)&ssData, sizeof(NetData));
    m_listClients[nIndex]->SendBytes(dataArray);
    //
    qDebug()<<"Sendto:  "<<m_listIPAndPorts[nIndex]<<" Bytes: "<<sizeof(NetData);

}

void DialogSrv::DeleteOneClient(QString strIPAndPort)
{
    int nIndex = m_listIPAndPorts.indexOf(strIPAndPort);
    if(nIndex < 0)
    {
        //序号出错
        return;
    }
    //删除对应客户端
    ui->listWidget->takeItem(nIndex);   //删除UI显示的那一个IP条目
    m_listIPAndPorts.removeAt(nIndex); //删除IP字符串列表对应条目
    m_listClients.removeAt(nIndex);//删除客户端

}







clientjog.h

#ifndef CLIENTJOBS_H
#define CLIENTJOBS_H

#include <QObject>
#include <QtNetwork>
#include "clientjobs.h"


class ClientJobs : public QObject
{
    Q_OBJECT
public:
    explicit ClientJobs(QObject *parent, QTcpSocket *client, QString strIPPort);
    //TCP连接
    QTcpSocket *m_pClientSock;
    QString m_strIPPort;//IP_Port


signals:
    void CallMainWindowDeleteClient(QString m_strIPPort);

public slots:
    void SendBytes(QByteArray &data);
    void LostConnection();


};

#endif // CLIENTJOBS_H

clientjob.cpp

#include "clientjobs.h"

ClientJobs::ClientJobs(QObject *parent, QTcpSocket *client, QString strIPPort) :
    QObject(parent)
{
    m_pClientSock = client;
    m_strIPPort = strIPPort;
    //关联信号
    connect(m_pClientSock, SIGNAL(disconnected()), this, SLOT(LostConnection()));
    //可以关联接收数据信号readyRead(),这里不管

}

void ClientJobs::SendBytes(QByteArray &data)
{
    m_pClientSock->write(data);
}

void ClientJobs::LostConnection()
{
    //通知主窗口删除自己
    emit CallMainWindowDeleteClient(m_strIPPort);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt 中创建本地 IP 套接字可以使用 QTcpSocket 类。下面是一个简单的示例代码,演示如何创建一个本地 IP 套接字: ```cpp #include <QtNetwork/QTcpSocket> #include <QtNetwork/QHostAddress> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTcpSocket socket; socket.connectToHost(QHostAddress::LocalHost, 8080); return a.exec(); } ``` 在上面的示例中,我们首先包含了 `QTcpSocket` 和 `QHostAddress` 头文件。然后,我们创建了一个 `QTcpSocket` 对象并调用了 `connectToHost()` 函数来连接到本地 IP 地址和端口号为 8080 的主机。在实际应用中,你需要根据你的需求来更改本地 IP 地址和端口号。 需要注意的是,如果你希望创建一个本地服务器套接字,你需要使用 `QTcpServer` 类。在服务器端,你需要监听来自本地 IP 地址和端口号的连接请求。以下是一个简单的示例代码,演示如何创建一个本地服务器套接字: ```cpp #include <QtNetwork/QTcpServer> #include <QtNetwork/QHostAddress> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTcpServer server; server.listen(QHostAddress::LocalHost, 8080); return a.exec(); } ``` 在上面的示例中,我们首先包含了 `QTcpServer` 和 `QHostAddress` 头文件。然后,我们创建了一个 `QTcpServer` 对象并调用了 `listen()` 函数来监听来自本地 IP 地址和端口号为 8080 的连接请求。在实际应用中,你需要根据你的需求来更改本地 IP 地址和端口号。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值