public function createFromString(&$address, &$scheme)
    {
        if ($scheme === null) {
            $scheme = 'tcp';
        }

        $hasScheme = false;

        $pos = strpos($address, '://');
        if ($pos !== false) {
            $scheme = substr($address, 0, $pos);
            $address = substr($address, $pos + 3);
            $hasScheme = true;
        }

        if (strpos($address, ':') !== strrpos($address, ':') && in_array($scheme, array('tcp', 'udp', 'icmp'))) {
            // TCP/UDP/ICMP address with several colons => must be IPv6
            $scheme .= '6';
        }

        if ($scheme === 'tcp') {
            $socket = $this->createTcp4();
        } elseif ($scheme === 'udp') {
            $socket = $this->createUdp4();
        } elseif ($scheme === 'tcp6') {
            $socket = $this->createTcp6();
        } elseif ($scheme === 'udp6') {
            $socket = $this->createUdp6();
        } elseif ($scheme === 'unix') {
            $socket = $this->createUnix();
        } elseif ($scheme === 'udg') {
            $socket = $this->createUdg();
        } elseif ($scheme === 'icmp') {
            $socket = $this->createIcmp4();
        } elseif ($scheme === 'icmp6') {
            $socket = $this->createIcmp6();
            if ($hasScheme) {
                // scheme was stripped from address, resulting IPv6 must not
                // have a port (due to ICMP) and thus must not be enclosed in
                // square brackets
                $address = trim($address, '[]');
            }
        } else {
            throw new InvalidArgumentException('Invalid address scheme given');
        }
        return $socket;
    }