qt利用腾讯云服务器实现不同局域网的通信(tcp)

网上大多数关于qt通信的文章都是同一局域网通信,这种根本没有达到自己想象中的那种通信的要求(不同局域网的通信)。这里用到的方法是客户端发送消息给服务器,然后服务器再发送给另一个局域网的客户。
首先我们需要购买一个腾讯云服务器,并在自己电脑登录腾讯云服务器的虚拟机。
在这里插入图片描述
点击这里的登录。
登录完成后,就需要把自己写的服务器架在虚拟机上(就是把自己写的服务器在虚拟机上运行)。
以下是我写的服务器代码
.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpServer>
#include<QTcpSocket>
#include<QList>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    void newConnectSoket(QTcpSocket *,QString);
    void send_data_to_user(QString);
    ~Widget();

private:
    Ui::Widget *ui;
    QTcpServer *tcpServer;
    QTcpSocket *tcpSoket;
    QMap<QString,QTcpSocket*> user_tcpSokets;//用户账号对应一个socket
    int client_Num;//用户数量
};
#endif // WIDGET_H

.cpp

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    client_Num=0;//初始化客户端数量
    tcpServer=new QTcpServer(this);
    tcpServer->listen(QHostAddress::AnyIPv4,8888);
    setWindowTitle("服务器:8888");
    connect(tcpServer,&QTcpServer::newConnection,
            [=]()
    {
        tcpSoket=tcpServer->nextPendingConnection();
        connect(tcpSoket,&QTcpSocket::readyRead,
                [=]()
        {
            QByteArray array=tcpSoket->readAll();
            char *m=array.data();
            QString dataStr=m;
            ui->textEdit->append(dataStr);
            qDebug()<<dataStr;
            if(dataStr.startsWith("Load"))
            {
                newConnectSoket(tcpSoket,dataStr);//当有新用户连接时,保存用户账号和socket
            }
            else if(dataStr.startsWith("Send"))
            {
                send_data_to_user(dataStr);//当有需要发送消息时
            }
        });

    });
}
void Widget::newConnectSoket(QTcpSocket *soket,QString str)
{
    qDebug()<<str;
    user_tcpSokets[str.section("#",1,1)]=soket;//保存
    tcpSoket->disconnect();//保存完关闭连接
}
void Widget::send_data_to_user(QString str)
{
    qDebug()<<str;
    tcpSoket=user_tcpSokets[str.section("#",1,1)];//获取需要发送到的账号对应的socket
    tcpSoket->write(str.section("#",2,2).toUtf8().data());//发送消息
    tcpSoket->disconnect();//关闭连接
}
Widget::~Widget()
{
    delete ui;
}


服务器架完之后就需要用客户端发送和接收消息了,这里只是个简单的测试,所以简单的写了两个测试的客户端。
客户端0001,用于接收客户端0002发送过来的消息
以下是0001客户端的代码
.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpSocket>
#include<QTextEdit>
#include<QGridLayout>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private:
    Ui::Widget *ui;
    QTcpSocket *tcpSoket;
    QTextEdit *text=new QTextEdit;
};
#endif // WIDGET_H

.cpp

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

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("客户端0001");
    tcpSoket=new QTcpSocket(this);
    tcpSoket->connectToHost("购买的云服务器的公网ip",8888);//打开应用首先连接服务器
    QString str=QString("Load#0001");//发送登录以及自己的账号给服务器
    tcpSoket->write(str.toUtf8().data());
    connect(tcpSoket,&QTcpSocket::readyRead,
            [=]()
    {
       QByteArray array=tcpSoket->readAll();
       ui->textEdit->append(array);
    });
}
Widget::~Widget()
{
    delete ui;
}


0002客户端的作用是给0001客户端发送消息。代码类似0001客户端的代码。以下是0002的代码。
.h(与0001一样)

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpSocket>
#include<QTextEdit>
#include<QGridLayout>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private:
    Ui::Widget *ui;
    QTcpSocket *tcpSoket;
    QTextEdit *text=new QTextEdit;
};
#endif // WIDGET_H

.cpp

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

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("客户端0001");
    tcpSoket=new QTcpSocket(this);
    tcpSoket->connectToHost("购买的云服务器的公网ip",8888);//打开应用首先连接服务器
    tcpSoket->write(QString("Send#0001#hello").toUtf8().data());
    connect(tcpSoket,&QTcpSocket::readyRead,
            [=]()
    {
       QByteArray array=tcpSoket->readAll();
       ui->textEdit->append(array);

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


以下是实现的效果
在这里插入图片描述
在这里插入图片描述
以上只是实现了不同局域网的简单通信,更多功能还需要自己拓展。

  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
### 回答1: 在局域网中出现丢包的情况,可能有以下原因: 1. 网络质量不佳:局域网内部网络质量不佳,可能导致数据包在传输过程中丢失,可以通过使用网络分析工具(如Wireshark)来分析网络传输情况,找出网络瓶颈并进行优化。 2. 通信协议问题:TCP协议是一种可靠的传输协议,但是在一些情况下,可能会出现丢包的情况,可以考虑使用UDP协议,但是使用UDP协议需要考虑数据的可靠性。 3. 程序设计问题:程序设计问题也可能导致数据包丢失,可以通过检查程序代码,尤其是网络通信相关的代码,找出问题并进行修复。 4. 防火墙或安全软件的干扰:防火墙或安全软件的设置可能会对网络通信造成干扰,可以尝试关闭相应的防火墙或安全软件,或者将程序添加到白名单中。 5. 硬件故障:硬件故障(如网卡故障、路由器故障等)也可能导致数据包丢失,可以通过更换硬件或者升级固件来解决问题。 希望以上解决方案能够解决你的问题。 ### 回答2: 在Qt中进行TCP通信时,局域网丢包问题可能由以下几个原因导致: 1. 网络负载过高:局域网中存在大量的数据传输时,网络的带宽可能会达到极限,导致丢包现象。这时我们可以尝试优化网络负载,使用更高速的网络设备或增加网络带宽。 2. 网络延迟:局域网中的设备之间可能存在一定的延迟,导致数据包发送和接收之间的时间差较大,从而引发丢包。我们可以尝试优化网络延迟,例如使用更快速的网络设备、优化网络拓扑等。 3. 网络不稳定:局域网中的网络连接可能会出现波动,导致数据包的传输中断或丢失。我们可以尝试使用稳定的网络设备,检查网络连接是否正常,检测可能的网络故障。 4. TCP协议问题:TCP协议作为一种可靠的传输协议,会进行数据包的校验和重传,但在某些情况下,可能由于网络环境等原因,TCP协议无法正确检测和处理丢包现象。我们可以尝试优化TCP协议的设置,例如调整超时重传时间、增加数据包重传次数等。 综上所述,Qt中的TCP通信局域网丢包问题可能由网络负载过高、网络延迟、网络不稳定和TCP协议问题等多个因素导致。我们可以根据具体情况分析和优化,以提高通信的可靠性和稳定性。 ### 回答3: Qt是一种跨平台的C++开发框架,能够帮助我们进行各种应用程序的开发,包括网络通信。在局域网中使用Qt进行TCP通信时,可能会出现丢包的问题。 TCP是一种可靠的传输协议,它通过检验和、重传机制等手段来保证数据的可靠传输。但是,在局域网中,由于网络拥堵、数据包丢失等原因,TCP通信仍然可能会丢包。 原因有以下几个可能: 1.网络拥堵:当局域网中的网络带宽不足或者有其他大量数据传输的情况下,数据包的丢失概率会增加。 2.网络抖动:局域网中的网络可能存在抖动现象,导致数据包的传输延迟或丢失。 3.路由问题:在局域网中,由于路由器设置不当或者网络拓扑结构的问题,可能会导致数据包传输的丢失。 解决这个问题的方法有以下几种: 1.优化网络环境:可以增加网络带宽,减少网络拥堵的情况。可以使用专用的网络设备或软件来监控和优化网络性能。 2.增加冗余性:可以通过在数据包中添加冗余的校验信息,如CRC校验码,来增加数据包的可靠性,减少丢包的概率。 3.重传机制:可以在通信协议中加入重传机制,当检测到数据包丢失时,及时重新发送数据包,确保数据的正确传输。 总之,Qt局域网中进行TCP通信时,丢包是一个常见的问题,但可以通过优化网络环境、增加冗余性和使用重传机制等方法来解决。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值