Search code examples
c++qtqtcpserver

Make QTcpServer accept only IPv4 connections


I'm implementing an FTP server, and it doesn't support IPv6 yet (IPv6 connections can't use PORT and PASV, they need to use EPRT and EPSV instead for specifying data connections).

So I need to accept only IPv4 connections from my QTcpServer. Right now I start listening with this code:

server->listen(QHostAddress::Any, port);

QHostAddress::Any is supposed to be the IPv4 any-address, but Filezilla still manages to connect using IPv6 when I specify localhost instead of 127.0.0.1. I thought that QHostAddress::Any would mean only IPv4 incoming connections are accepted, but that's obviously not the case.

So how can I disable IPv6 connections?


Solution

  • In Qt4, QHostAddress::Any used to listen for IPv4 only, but as of Qt5, it now listens on all available interfaces.

    If you want to compile under both Qt4, and Qt5, your code should look like this:

    #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
        server->listen(QHostAddress::AnyIPv4, port);
    #else
        server->listen(QHostAddress::Any, port);
    #endif
    

    As Qt5 reference says:

    QHostAddress::Any The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces.

    Based on the QTcpServer reference you should use

    QHostAddress::AnyIPv4
    

    QHostAddress::AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interaces.


    Side note: what it does under the hood is creating correct version of socket, i.e. AF_INET or AF_INET6:

    int ipv4sockfd = socket( AF_INET, SOCK_STREAM, 0);
    
    int ipv6sockfd = socket( AF_INET6, SOCK_STREAM, 0);