PHPackages                             icicleio/dns - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. icicleio/dns

ActiveLibrary[Queues &amp; Workers](/categories/queues)

icicleio/dns
============

Asynchronous DNS for Icicle.

v0.6.0(10y ago)648.7k↓16.7%12MITPHP

Since Apr 9Pushed 10y ago2 watchersCompare

[ Source](https://github.com/icicleio/dns)[ Packagist](https://packagist.org/packages/icicleio/dns)[ Docs](http://icicle.io)[ RSS](/packages/icicleio-dns/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (7)Versions (13)Used By (2)

Asynchronous DNS for Icicle
===========================

[](#asynchronous-dns-for-icicle)

This library is a component for [Icicle](https://github.com/icicleio/Icicle), providing an asynchronous DNS query executor, resolver, and client connector. An asynchronous DNS server is currently under development and will be added to this component in the future. Like other Icicle components, this library uses [Coroutines](//github.com/icicleio/icicle/wiki/Coroutines) built from [Awaitables](https://github.com/icicleio/icicle/wiki/Awaitables) and [Generators](http://www.php.net/manual/en/language.generators.overview.php) to make writing asynchronous code more like writing synchronous code.

[![Build Status](https://camo.githubusercontent.com/2326e472d2ac1ef827d0fb785f7ca4fb3458d1b23f39ac749c2e24e39998afee/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f696369636c65696f2f646e732f76312e782e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/icicleio/dns)[![Coverage Status](https://camo.githubusercontent.com/fea59e8928ef9dc096cdcca804a191e5d84dc4b4f201af2d526ecfa5e5b241d7/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f696369636c65696f2f646e732f76312e782e7376673f7374796c653d666c61742d737175617265)](https://coveralls.io/r/icicleio/dns)[![Semantic Version](https://camo.githubusercontent.com/2b14b3ca99a226f7f62c286ecdc77ed6fe02141fc7e2b8db22f34a01db22c57e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f696369636c65696f2f646e732e7376673f7374796c653d666c61742d737175617265)](http://semver.org)[![MIT License](https://camo.githubusercontent.com/ededa194de88a93884ad8b4368f0e8fa3618dae77cbc94a9e6efb6c2f378d180/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f696369636c65696f2f646e732e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![@icicleio on Twitter](https://camo.githubusercontent.com/fb16a2e03bb85dd9926a15e837d3754b7766046281e2698271930aadbcd972cf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f747769747465722d253430696369636c65696f2d3531383963372e7376673f7374796c653d666c61742d737175617265)](https://twitter.com/icicleio)

##### Requirements

[](#requirements)

- PHP 5.5+ for v0.6.x branch (current stable) and v1.x branch (mirrors current stable)
- PHP 7 for v2.0 branch (under development) supporting generator delegation and return expressions

##### Installation

[](#installation)

The recommended way to install is with the [Composer](http://getcomposer.org/) package manager. (See the [Composer installation guide](https://getcomposer.org/doc/00-intro.md) for information on installing and using Composer.)

Run the following command to use this library in your project:

```
composer require icicleio/dns
```

You can also manually edit `composer.json` to add this library as a project requirement.

```
// composer.json
{
    "require": {
        "icicleio/dns": "^0.6"
    }
}
```

#### Example

[](#example)

The example below uses the `Icicle\Dns\resolver()` function to asynchronously find the IP address for the domain `icicle.io`.

```
use Icicle\Coroutine\Coroutine;
use Icicle\Dns;
use Icicle\Loop;

$generator = function ($domain) {
    try {
        $ips = (yield Dns\resolve($domain));

        foreach ($ips as $ip) {
            echo "IP: {$ip}\n";
        }
    } catch (Exception $exception) {
        echo "Error when executing query: {$exception->getMessage()}\n";
    }
};

$coroutine = new Coroutine($generator('icicle.io'));
$coroutine->done();

Loop\run();
```

Documentation
-------------

[](#documentation)

- [Executors](#executors) - Executes a DNS query.
    - [Creating an Executor](#creating-an-executor)
    - [execute() function](#execute-function)
    - [Using an Executor](#using-an-executor)
    - [MultiExecutor](#multiexecutor)
- [Resolver](#resolver) - Resolves the IP address for a domain name.
    - [resolve() function](#resolve-function)
- [Connector](#connector) - Connects to a host and port.
    - [connect() function](#connect-function)

Methods returning a `Generator` can be used to create a [Coroutine](https://github.com/icicleio/icicle/wiki/Coroutines) (e.g., `new Coroutine($executor->execute(...))`) or yielded within another Coroutine (use `yield from` in PHP 7 for better performance).

This library uses [LibDNS](//github.com/DaveRandom/LibDNS) to create and parse DNS messages. Unfortunately the documentation for this library is currently limited to DocComments in the source code. If only using resolvers and connectors in this library, there is no need to worry about how LibDNS works. Executors returns coroutines that are resolved with `LibDNS\Messages\Message` instances, representing the response from the DNS server. Using these objects is simple and will be described in the executor section below.

#### Function prototypes

[](#function-prototypes)

Prototypes for object instance methods are described below using the following syntax:

```
ClassOrInterfaceName::methodName(ArgumentType $arg): ReturnType
```

Executors
---------

[](#executors)

Executors are the foundation of the DNS component, performing any DNS query and returning the full results of that query. Resolvers and connectors depend on executors to perform the DNS query required for their operation.

Each executor implements `Icicle\Dns\Executor\Executor` that defines a single method, `execute()`.

```
Executor::execute(
    string $domain,
    string|int $type,
    array $options = []
): \Generator
```

OptionTypeDescription`timeout``float`Timeout until query fails. Default is 2 seconds.`retries``int`Number of times to attempt the query before failing. Default is 5 times.An executor will retry a query a number of times if it doesn't receive a response within `timeout` seconds. The number of times a query will be retried before failing is defined by `retries`, with `timeout` seconds elapsing between each query attempt.

ResolutionTypeDescriptionFulfilled`LibDNS\Message\Message`Query response. Usage described below.Rejected`Icicle\Dns\Exception\FailureException`If sending the request or parsing the response fails.Rejected`\Icicle\Dns\Exception\MessageException`If the server returns a non-zero response code or no response is received.### execute() Function

[](#execute-function)

The simplest way to perform a DNS query is to use the `Icicle\Dns\execute()` function. This function uses an `Icicle\Dns\Executor\Executor` object that can be set or retrieved using the `Icicle\Dns\executor()` function.

```
`Icicle\Dns\execute(
    string $domain,
    string|int $type,
    array $options = []
): \Generator
```

Example using the `execute()` function to find the A record for a domain:

```
use Icicle\Coroutine\Coroutine;
use Icicle\Dns;
use Icicle\Loop;
use LibDNS\Messages\Message;

$coroutine = new Coroutine(Dns\execute('google.com', 'A'));

$coroutine->done(
    function (Message $message) {
        foreach ($message->getAnswerRecords() as $resource) {
            echo "TTL: {$resource->getTTL()} Value: {$resource->getData()}\n";
        }
    },
    function (Exception $exception) {
        echo "Query failed: {$exception->getMessage()}\n";
    }
);

Loop\run();
```

### Creating an Executor

[](#creating-an-executor)

The simplest executor is `Icicle\Dns\Executor\BasicExecutor`, created by providing the constructor with the IP address of a DNS server to use to perform queries. It is recommended to use a DNS server closest to you, such as the local router. If this is not possible, Google operates two DNS server that also can be used at `8.8.8.8` and `8.8.4.4`.

```
use Icicle\Dns\Executor\BasicExecutor;

$executor = new BasicExecutor('8.8.8.8');
```

The `Icicle\Dns\Executor\BasicExecutor` constructor also accepts an instance of `Icicle\Socket\Connector\Connector` as the second argument if custom behavior is desired when connecting to the name server. If no instance is given, the default global connector is used (see `Icicle\Socket\connector()`).

### Using an Executor

[](#using-an-executor)

Once created, an executor is used by calling the `execute()` method with the domain and type of DNS query to be performed. The type may be a case-insensitive string naming a record type (e.g., `'A'`, `'MX'`, `'NS'`, `'PTR'`, `'AAAA'`) or the integer value corresponding to a record type (`LibDNS\Records\ResourceQTypes` defines constants corresponding to a the integer value of a type). `execute()` returns a coroutine fulfilled with an instance of `LibDNS\Messages\Message` that represents the response from the name server. `LibDNS\Messages\Message` objects have several methods that will need to be used to fetch the data in the response.

- `getAnswerRecords()`: Returns an instance of `LibDNS\Records\RecordCollection`, a traversable collection of `LibDNS\Record\Resource` objects containing the response answer records.
- `getAuthorityRecords()`: Returns an instance of `LibDNS\Records\RecordCollection` containing the response authority records.
- `getAdditionalRecords()`: Returns an instance of `LibDNS\Records\RecordCollection` containing the response additional records.
- `getAuthorityRecords()`: Returns an instance of `LibDNS\Records\RecordCollection` containing the response authority records.
- `isAuthoritative()`: Determines if the response is authoritative for the records returned.

DNS records in the traversable `LibDNS\Records\RecordCollection` objects are represented as instances of `LibDNS\Records\Resource`. These objects have several methods to access the data associated with the record.

- `getType()`: Returns the record type as an `integer`.
- `getName()`: Gets the domain name associated with the record as a `string`.
- `getData()`: Returns an `LibDNS\Records\RData` instance representing the records data. This object may be cast to a `string` or each field can be accessed with the `LibDNS\Records\RData::getField(int $index)` method. The number of fields in a resource depends on the type of resource (e.g., `MX` records contain two fields, a priority and a host name).
- `getTTL()`: Gets the TTL (time-to-live) as an `integer`.

Below is an example of how an executor can be used to find the NS records for a domain.

```
use Icicle\Coroutine\Coroutine;
use Icicle\Dns\Executor\BasicExecutor;
use Icicle\Loop;
use LibDNS\Messages\Message;

$executor = new BasicExecutor('8.8.8.8');

$coroutine = new Coroutine($executor->execute('google.com', 'NS'));

$coroutine->done(
    function (Message $message) {
        foreach ($message->getAnswerRecords() as $resource) {
            echo "TTL: {$resource->getTTL()} Value: {$resource->getData()}\n";
        }
    },
    function (Exception $exception) {
        echo "Query failed: {$exception->getMessage()}\n";
    }
);

Loop\run();
```

### MultiExecutor

[](#multiexecutor)

The `Icicle\Dns\Executor\MultiExecutor` class can be used to combine multiple executors to send queries to several name servers so queries can be resolved even if some name servers stop responding.

```
use Icicle\Coroutine\Coroutine;
use Icicle\Dns\Executor\BasicExecutor;
use Icicle\Dns\Executor\MultiExecutor;
use Icicle\Loop;
use LibDNS\Messages\Message;

$executor = new MultiExecutor();

$executor->add(new BasicExecutor('8.8.8.8'));
$executor->add(new BasicExecutor('8.8.4.4'));

// Executor will send query to 8.8.4.4 if 8.8.8.8 does not respond.
$coroutine = new Coroutine($executor->execute('google.com', 'MX'));

$coroutine->done(
    function (Message $message) {
        foreach ($message->getAnswerRecords() as $resource) {
            echo "TTL: {$resource->getTTL()} Value: {$resource->getData()}\n";
        }
    },
    function (Exception $exception) {
        echo "Query failed: {$exception->getMessage()}\n";
    }
);

Loop\run();
```

Queries using the above executor will automatically send requests to the second name server if the first does not respond. Subsequent queries are initially sent to the last server that successfully responded to a query.

Resolver
--------

[](#resolver)

A resolver finds the IP addresses for a given domain. `Icicle\Dns\Resolver\BasicResolver` implements `Icicle\Dns\Resolver\Resolver`, which defines a single method, `resolve()`. A resolver is essentially a specialized executor that performs only `A` queries, fulfilling the coroutine returned from `resolve()` with an array of IP addresses (even if only one or zero IP addresses is found, the coroutine is still resolved with an array).

```
Resolver::resolve(
    string $domain,
    array $options = []
): \Generator
```

OptionTypeDescription`mode``int`Resolution mode: IPv4 or IPv6. Use the constants `ResolverInterface::IPv4` or ``ResolverInterface::IPv6`.`timeout``float`Timeout until query fails. Default is 2 seconds.`retries``int`Number of times to attempt the query before failing. Default is 5 times.### resolve() Function

[](#resolve-function)

The simplest way find the IP address for a domain is to use the `Icicle\Dns\resolve()` function. This function uses an `Icicle\Dns\Resolver\Resolver` object that can be set or retrieved using the `Icicle\Dns\resolver()` function.

```
`Icicle\Dns\resolve(
    string $domain,
    array $options = []
): \Generator
```

Example using the `resolve()` function to resolve the IP address of a domain:

```
use Icicle\Coroutine\Coroutine;
use Icicle\Dns;
use Icicle\Loop;

$coroutine = new Coroutine(Dns\resolve('google.com'));

$coroutine->done(
    function (array $ips) {
        foreach ($ips as $ip) {
            echo "IP: {$ip}\n";
        }
    },
    function (Exception $exception) {
        echo "Query failed: {$exception->getMessage()}\n";
    }
);

Loop\run();
```

Like executors, a resolver will retry a query `retries` times if the name server does not respond within `timeout` seconds.

The `Icicle\Resolver\BasicResolver` class is constructed by passing an `Icicle\Executor\Executor` instance that is used to execute queries to resolve domains. If no executor is given, one will be created by default, using `8.8.8.8` and `8.8.4.4` as DNS servers for the executor.

ResolutionTypeDescriptionFulfilled`array`Array of resolved IP addresses. May be empty.Rejected`Icicle\Dns\Exception\FailureException`If sending the request or parsing the response fails.Rejected`\Icicle\Dns\Exception\MessageException`If the server returns a non-zero response code or no response is received.##### Example

[](#example-1)

```
use Icicle\Coroutine\Coroutine;
use Icicle\Dns\Resolver\BasicResolver;
use Icicle\Loop;

$resolver = new BasicResolver();

$coroutine = new Coroutine($resolver->resolve('google.com'));

$coroutine->done(
    function (array $ips) {
        foreach ($ips as $ip) {
            echo "IP: {$ip}\n";
        }
    },
    function (Exception $exception) {
        echo "Query failed: {$exception->getMessage()}\n";
    }
);

Loop\run();
```

Connector
---------

[](#connector)

The connector component connects to a server by first resolving the hostname provided, then making the connection and resolving the returned coroutine with an instance of `Icicle\Socket\Socket`.

`Icicle\Dns\Connector\Connector` defines a single method, `connect()` that should resolve a host name and connect to one of the resolved servers, resolving the coroutine with the connected client.

```
Connector::connect(
    string $domain,
    int $port,
    array $options = [],
): \Generator
```

### connect() Function

[](#connect-function)

The simplest way to resolve a domain name and connect to a port on the resolved host is with the `Icicle\Dns\connect()` function. This function uses an `Icicle\Dns\Connector\Connector` object that can be set or retrieved using the `Icicle\Dns\connector()` function.

```
`Icicle\Dns\connect(
    string $domain,
    int $port,
    array $options = []
): \Generator
```

Example using the `connect()` function to resolve the IP address of a domain and connect to port 443:

```
use Icicle\Dns;
use Icicle\Loop;
use Icicle\Socket\Socket;

$connector = new DefaultConnector();

$coroutine = new Coroutine(Dns\connect('google.com', 443));

$coroutine->done(
    function (Socket $client) {
        echo "IP: {$client->getRemoteAddress()}\n";
        echo "Port: {$client->getRemotePort()}\n";
    },
    function (Exception $exception) {
        echo "Connecting failed: {$exception->getMessage()}\n";
    }
);

Loop\run();
```

`Icicle\Dns\Connector\DefaultConnector` will attempt to connect to one of the IP addresses found for a given host name. If the server at that IP is unresponsive, the connector will attempt to establish a connection to the next IP in the list until a server accepts the connection. Only if the connector is unable to connect to all of the IPs will it reject the coroutine returned from `connect()`. The constructor also optionally accepts an instance of `Icicle\Socket\Connector\Connector` if custom behavior is desired when connecting to the resolved host.

OptionTypeDescription`mode``int`Resolution mode: IPv4 or IPv6. Use the constants `Resolver::IPv4` or ``Resolver::IPv6`.`timeout``float`Timeout until query fails. Default is 2 seconds.`retries``int`Number of times to attempt the query before failing. Default is 5 times.Additionally, all the [other options available](https://github.com/icicleio/socket#connect) to `Icicle\Socket\Connector\Connector::connect()` may also be used.

ResolutionTypeDescriptionFulfilled`Icicle\Socket\Socket`Connected client.Rejected`Icicle\Socket\Exception\FailureException`If resolving the IP or connecting fails.##### Example

[](#example-2)

```
use Icicle\Dns\Connector\DefaultConnector;
use Icicle\Loop;
use Icicle\Socket\Socket;

$connector = new DefaultConnector();

$coroutine = new Coroutine($connector->connect('google.com', 80));

$coroutine->done(
    function (Socket $client) {
        echo "IP: {$client->getRemoteAddress()}\n";
        echo "Port: {$client->getRemotePort()}\n";
    },
    function (Exception $exception) {
        echo "Connecting failed: {$exception->getMessage()}\n";
    }
);

Loop\run();
```

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity33

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 98.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~21 days

Total

12

Last Release

3816d ago

Major Versions

v0.6.0 → 1.x-dev2015-12-07

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1628287?v=4)[Aaron Piotrowski](/maintainers/Trowski)[@trowski](https://github.com/trowski)

---

Top Contributors

[![trowski](https://avatars.githubusercontent.com/u/1628287?v=4)](https://github.com/trowski "trowski (117 commits)")[![assertchris](https://avatars.githubusercontent.com/u/200609?v=4)](https://github.com/assertchris "assertchris (2 commits)")

---

Tags

asyncasynchronousdnsresolver

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/icicleio-dns/health.svg)

```
[![Health](https://phpackages.com/badges/icicleio-dns/health.svg)](https://phpackages.com/packages/icicleio-dns)
```

###  Alternatives

[amphp/amp

A non-blocking concurrency framework for PHP applications.

4.4k123.4M323](/packages/amphp-amp)[revolt/event-loop

Rock-solid event loop for concurrent PHP applications.

92343.6M138](/packages/revolt-event-loop)[amphp/parallel

Parallel processing component for Amp.

85046.2M74](/packages/amphp-parallel)[react/dns

Async DNS resolver for ReactPHP

536114.1M100](/packages/react-dns)[amphp/dns

Async DNS resolution for Amp.

19339.2M41](/packages/amphp-dns)[amphp/sync

Non-blocking synchronization primitives for PHP based on Amp and Revolt.

19052.8M39](/packages/amphp-sync)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
