【问题标题】:How to compare IP of the requested client connection to one of the recognized IP's in QTcpSocket class?如何将请求的客户端连接的 IP 与 QTcpSocket 类中已识别的 IP 之一进行比较?
【发布时间】:2018-01-13 09:44:15
【问题描述】:

我的主要问题是:我有一个已识别 IP 的列表,并且我正在执行多线程 TCP 客户端-服务器通信;因此,每当新的连接请求来自任何随机客户端(服务器一直在侦听)时,我想首先将该 IP 与存储的 IP 进行比较,并且仅当它是我认可的 IP 之一时才允许新连接。硬盘上可以有一个 .txt 文件,也可以是 QListQString 哪个更好的解决方案。

编辑:为了清楚起见,以下是我目前开发的 server.cpp 文件以及我遇到的错误目前有。

#include "myserver.h"
#include "ioprogram.h"
#include <string>
#include <iostream>

using namespace std;

//string ClientInfo;

MyServer::MyServer(QObject *parent): QTcpServer(parent)
{
    QStringList accepted_ip_list;   //List of remote IPs that can be accepted in QString list format
    accepted_ip_list.append("127.0.0.1");   // IPv4 local address
    accepted_ip_list.append("::1");         // IPv6 local address

    // Convert from QString to integer format, generating new list
    foreach (const QString &ip, accepted_ip_list)
    {
        QHostAddress host_address(ip);
        my_accepted_ip_list.append(host_address);
    }

    myserver = new QTcpServer(this);

    connect(myserver, &QTcpServer::incomingConnection, this, &MyServer::incomingConnection);

    myserver->listen(QHostAddress::Any, 1234);
}

void MyServer::startServer()
{
    if(!this->listen(QHostAddress::Any,1234))
    {
        qDebug() << "Could not start server.";
    }
    else
    {
        qDebug() << "Listening...";
    }
}

void MyServer::incomingConnection(qintptr socketDescriptor)
{
    qDebug() << socketDescriptor << "Connecting...";

    while (myserver->hasPendingConnections())
    {
        QTcpSocket *socket = myserver->nextPendingConnection();
        QHostAddress host_address = socket->peerAddress();

        bool contains = false;

        for(int i=0; i < my_accepted_ip_list.size(); i++)
        {
            if(my_accepted_ip_list[i].isEqual(host_address,QHostAddress::ConvertV4MappedToIPv4))
            {
                contains = true;
                break;
            }
        }

        if(contains)
        {
            MyThread *thread = new MyThread(socketDescriptor, this);

            connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
            thread->start();
        }
        else
        {
            socket->abort();        // Reject peer by disconnecting it
            socket->deleteLater();  // Schedule the socket removal from memory
        }
    }
}

以下是错误:

1) @line10 --- 'MyServer::MyServer(QObject*)' 的原型与 'MyServer' 类中的任何一个都不匹配

2) @line55 --- 类“QHostAddress”没有名为“isEqual”的成员

3) @line55 --- 'ConvertV4MappedToIPv4' 不是 'QHostAddress' 的成员

这是头文件:

#ifndef MYSERVER_H
#define MYSERVER_H

#include <QTcpServer>
#include <QDebug>
#include "mythread.h"
//#include "ioprogram.h"

class MyServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit MyServer(QTcpServer *parent = nullptr);
    void startServer();

signals:

private slots:
//    void newConnection();

private:
    QTcpServer *myserver;
    QList<QHostAddress> my_accepted_ip_list;    //List of IPv4 addresses allowed by the server, in quint32 not QString

protected:
    void incomingConnection(qintptr socketDescriptor);
};
#endif // MYSERVER_H

头文件中有一个错误: 候选人是:MyServer::MyServer(MyServer&&)

【问题讨论】:

    标签: c++ multithreading qt qtcpsocket qtcpserver


    【解决方案1】:

    如果我是正确的,你正在寻找 peerAddress 给你一个 QHostAddress

    如何接受和拒绝对等点的简单示例:

    编辑:由于您使用 IP 作为安全资源,我建议您使用QSslSocket 进行加密和真实性。并联系一些安全专家,我不是;)

    EDIT2:添加了对 IPv6 比较的支持。

    EDIT3:修改的比较方法。

    标头示例(myserver.h 文件):

    #ifndef MYSERVER_H
    #define MYSERVER_H
    
    #include <QTcpServer>
    #include <QTcpSocket>
    #include <QDebug>
    
    class MyServer : public QTcpServer
    {
        Q_OBJECT
    public:
        explicit MyServer(QObject *parent = nullptr);
    
        void startServer();
    
    private:
        QList<QHostAddress> my_accepted_ip_list;    //List of addresses allowed by the server, in QHostAddress not QString
    
    protected:
        void incomingConnection(qintptr socketDescriptor);
    };
    
    #endif // MYSERVER_H
    

    CPP 文件示例(myserver.cpp 文件):

    #include "myserver.h"
    
    MyServer::MyServer(QObject *parent) : QTcpServer(parent)
    {
        QStringList accepted_ip_list;   //List of remote IPs that can be accepted in QString list format
        accepted_ip_list.append("127.0.0.1");   // IPv4 local address
        accepted_ip_list.append("::1");         // IPv6 local address
    
        // Convert from QString to QHostAddress format, generating new list
        foreach (const QString &ip, accepted_ip_list)
        {
            QHostAddress host_address(ip);
            my_accepted_ip_list.append(host_address);
        }
    }
    
    void MyServer::startServer()
    {
        if (!listen(QHostAddress::Any, 1234))
        {
            qDebug() << "Could not start server.";
        }
        else
        {
            qDebug() << "Listening...";
        }
    }
    
    void MyServer::incomingConnection(qintptr socketDescriptor)
    {
        QTcpSocket *socket = new QTcpSocket(this);
        socket->setSocketDescriptor(socketDescriptor);
    
        QHostAddress host_address = socket->peerAddress();
    
        quint32 ipv4 = host_address.toIPv4Address();
    
        QByteArray ipv6 = QByteArray((char*)host_address.toIPv6Address().c, 16);
    
        bool contains = false;
    
        for (int i = 0; i < my_accepted_ip_list.size(); i++)
        {
            quint32 accepted_ipv4 = my_accepted_ip_list[i].toIPv4Address();
            QByteArray accepted_ipv6 = QByteArray((char*)my_accepted_ip_list[i].toIPv6Address().c, 16);
    
            if (accepted_ipv4 == ipv4 || accepted_ipv6 == ipv6)
            {
                contains = true;
                break;
            }
        }
    
        if (contains)
        {
            qDebug() << qPrintable(socket->peerAddress().toString()) << "Accepted";
        }
        else
        {
            qDebug() << qPrintable(socket->peerAddress().toString()) << "Rejected";
            socket->abort();        // Reject peer by disconnecting it
            socket->deleteLater();  // Schedule the socket removal from memory
        }
    }
    

    【讨论】:

    • 我理解你的代码,我相信它会在我的程序中工作,但我无法初始化 m_server 实例;可以请你指教。
    • 非常感谢您的帮助,但不幸的是我仍然无法运行我的程序。编译时出错:类型 QObject 不是 'MyServer' 的直接基础
    • 请参阅我的帖子,该帖子现在包含代码和正在尝试解决的错误。谢谢:)
    • @Shahwani:我已根据您的代码进行了编辑,请参阅。 QHostAddress 的问题可能是由使用 Qt 5.8 之前的 Qt 版本引起的。见here
    • 非常感谢!现在我的代码运行没有错误。但仍然只有一个问题:我使用另一台笔记本电脑并通过以下命令附加其 IP:accepted_ip_list.append("172.18.48.139"); 但服务器仍然拒绝该连接;我用qDebug() &lt;&lt; "Rejected";看有没有被拒!
    猜你喜欢
    • 1970-01-01
    • 2016-07-30
    • 2019-06-20
    • 2019-10-12
    • 2011-03-07
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 2014-11-28
    相关资源
    最近更新 更多