diff --git a/include/opendht/peer_discovery.h b/include/opendht/peer_discovery.h
index 862f9c5fbacd36b125de87cd85238c3ae3731444..6f607741e795959d85f06d169d2ca11eaaec1f0c 100644
--- a/include/opendht/peer_discovery.h
+++ b/include/opendht/peer_discovery.h
@@ -23,7 +23,7 @@
 
 #include <string.h>
 #include <stdio.h>
-#include <unistd.h> 
+#include <unistd.h>
 
 #include <thread>
 #include <mutex>
@@ -39,7 +39,7 @@ public:
 
     PeerDiscovery(sa_family_t domain, in_port_t port);
     ~PeerDiscovery();
-    
+
     /**
      * startDiscovery - Keep Listening data from the sender until node is joinned or stop is called
     */
@@ -63,13 +63,11 @@ public:
     /**
      * Join the threads
     */
-    void join(){
-
-        if(running_listen.joinable()){ running_listen.join(); };
-        if(running_send.joinable()){ running_send.join(); };
-
+    void join() {
+        if(running_listen.joinable()) running_listen.join();
+        if(running_send.joinable()) running_send.join();
     }
-    
+
 private:
     std::mutex mtx_;
     std::condition_variable cv_;
@@ -82,13 +80,13 @@ private:
     SockAddr sockAddrSend_;
     std::array<uint8_t,dht::InfoHash::size() + sizeof(in_port_t)> data_send_;
 
-    //Thread export to be joined 
+    //Thread export to be joined
     std::thread running_listen;
     std::thread running_send;
     dht::InfoHash nodeId_;
 
     /**
-     * Multicast Socket Initialization, accept IPV4, IPV6 
+     * Multicast Socket Initialization, accept IPV4, IPV6
     */
     static int initialize_socket(sa_family_t domain);
 
@@ -134,11 +132,6 @@ private:
         return (uint32_t)lit_int[0] <<  0
             |  (uint32_t)lit_int[1] <<  8;
     }
-
-#ifdef _WIN32
-    WSADATA wsaData;
-#endif
-
 };
 
 }
diff --git a/include/opendht/sockaddr.h b/include/opendht/sockaddr.h
index 684c4a03d03b913dc991f91af3cdd9cbd9110450..c622573aa58f698aafa0dcf40c7867ab5cce7d1b 100644
--- a/include/opendht/sockaddr.h
+++ b/include/opendht/sockaddr.h
@@ -91,8 +91,6 @@ public:
 
     static std::vector<SockAddr> resolve(const std::string& host, const std::string& service = {});
 
-    static SockAddr parse(sa_family_t family, const char* address);
-
     bool operator<(const SockAddr& o) const {
         if (len != o.len)
             return len < o.len;
@@ -193,6 +191,12 @@ public:
         }
     }
 
+    /**
+     * Set the address part of the socket address from a numeric IP address (string representation).
+     * Family must be already set. Throws in case of parse failue.
+     */
+    void setAddress(const char* address);
+
     /**
      * Returns the accessible byte length at the pointer returned by #get().
      * If zero, #get() returns null.
diff --git a/src/peer_discovery.cpp b/src/peer_discovery.cpp
index b4885a2205fce3e3067dc1b1a37ea1184c9d1ea5..984b7dbbfeb33fccc53cf35363506fa07177aeae 100644
--- a/src/peer_discovery.cpp
+++ b/src/peer_discovery.cpp
@@ -29,7 +29,7 @@
 namespace dht {
 
 constexpr char MULTICAST_ADDRESS_IPV4[10] = "224.0.0.1";
-constexpr char MULTICAST_ADDRESS_IPV6[8] = "ff02::1";
+constexpr char MULTICAST_ADDRESS_IPV6[8] = "ff05::2"; // Site-local multicast
 
 #ifdef _WIN32
 
@@ -66,12 +66,10 @@ PeerDiscovery::PeerDiscovery(sa_family_t domain, in_port_t port)
 int
 PeerDiscovery::initialize_socket(sa_family_t domain)
 {
-
 #ifdef _WIN32
-    // Initialize Windows Socket API with given VERSION.
+    WSADATA wsaData;
     if (WSAStartup(0x0101, &wsaData)) {
-        perror("WSAStartup");
-        throw std::runtime_error(std::string("Socket Creation Error_initialize_socket ") + strerror(errno));
+        throw std::runtime_error(std::string("Can't initialize Winsock2 ") + strerror(errno));
     }
 #endif
 
@@ -85,7 +83,7 @@ PeerDiscovery::initialize_socket(sa_family_t domain)
 
 void
 PeerDiscovery::listener_setup()
-{   
+{
     SockAddr sockAddrListen_;
     sockAddrListen_.setFamily(domain_);
     sockAddrListen_.setPort(port_);
@@ -107,58 +105,52 @@ PeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family)
 {
     switch (family)
     {
-        case AF_INET:{
-
-            ip_mreq config_ipv4;
-            
-            //This option can be used to set the interface for sending outbound 
-            //multicast datagrams from the sockets application.
-            config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY);
-            if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &config_ipv4.imr_interface, sizeof( struct in_addr )) < 0 ) {
-                throw std::runtime_error(std::string("Bound Network Interface IPV4 Error: ") + strerror(errno));
-            }
-
-            //The IP_MULTICAST_TTL socket option allows the application to primarily 
-            //limit the lifetime of the packet in the Internet and prevent it from circulating indefinitely
-            unsigned char ttl4 = 20;
-            if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl4, sizeof( ttl4 )) < 0 ) {
-                throw std::runtime_error(std::string(" TTL Sockopt Error: ") + strerror(errno));
-            }
-            
-            // config the listener to be interested in joining in the multicast group
-            config_ipv4.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDRESS_IPV4);
-            config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY);
-            if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&config_ipv4, sizeof(config_ipv4)) < 0){
-                throw std::runtime_error(std::string(" Member Addition IPV4 Error: ") + strerror(errno));
-            }
-
-            break;
+    case AF_INET:{
+        ip_mreq config_ipv4;
+
+        //This option can be used to set the interface for sending outbound
+        //multicast datagrams from the sockets application.
+        config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY);
+        if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &config_ipv4.imr_interface, sizeof( struct in_addr )) < 0 ) {
+            throw std::runtime_error(std::string("Bound Network Interface IPV4 Error: ") + strerror(errno));
         }
-    
-        case AF_INET6:{
-
-            ipv6_mreq config_ipv6;
 
-            unsigned int outif = 0;
-            if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &outif, sizeof( outif )) < 0 ) {
-                throw std::runtime_error(std::string("Bound Network Interface IPV6 Error: ") + strerror(errno));
-            }
+        //The IP_MULTICAST_TTL socket option allows the application to primarily
+        //limit the lifetime of the packet in the Internet and prevent it from circulating indefinitely
+        unsigned char ttl4 = 20;
+        if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl4, sizeof( ttl4 )) < 0 ) {
+            throw std::runtime_error(std::string(" TTL Sockopt Error: ") + strerror(errno));
+        }
 
-            unsigned int ttl6 = 20;
-            if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl6, sizeof( ttl6 )) < 0 ) {
-                throw std::runtime_error(std::string("Hop Count Set Error: ") + strerror(errno));
-            }
+        // config the listener to be interested in joining in the multicast group
+        config_ipv4.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDRESS_IPV4);
+        config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY);
+        if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&config_ipv4, sizeof(config_ipv4)) < 0){
+            throw std::runtime_error(std::string(" Member Addition IPV4 Error: ") + strerror(errno));
+        }
+        break;
+    }
+    case AF_INET6: {
+        ipv6_mreq config_ipv6;
 
-            config_ipv6.ipv6mr_interface = 0;
-            inet_pton(AF_INET6, MULTICAST_ADDRESS_IPV6, &config_ipv6.ipv6mr_multiaddr);
-            if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &config_ipv6, sizeof(config_ipv6)) < 0){
-                throw std::runtime_error(std::string("Member Addition IPV6 Error: ") + strerror(errno));
-            }
+        unsigned int outif = 0;
+        if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &outif, sizeof( outif )) < 0 ) {
+            throw std::runtime_error(std::string("Bound Network Interface IPV6 Error: ") + strerror(errno));
+        }
 
-            break;
+        unsigned int ttl6 = 20;
+        if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl6, sizeof( ttl6 )) < 0 ) {
+            throw std::runtime_error(std::string("Hop Count Set Error: ") + strerror(errno));
         }
 
-    }      
+        config_ipv6.ipv6mr_interface = 0;
+        inet_pton(AF_INET6, MULTICAST_ADDRESS_IPV6, &config_ipv6.ipv6mr_multiaddr);
+        if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &config_ipv6, sizeof(config_ipv6)) < 0){
+            throw std::runtime_error(std::string("Member Addition IPV6 Error: ") + strerror(errno));
+        }
+        break;
+    }
+    }
 }
 
 void
@@ -205,7 +197,8 @@ PeerDiscovery::sender_setup(const dht::InfoHash& nodeId, in_port_t port_to_send)
 {
     nodeId_ = nodeId;
     //Set up for Sender
-    sockAddrSend_ = SockAddr::parse(domain_, domain_ == AF_INET ? MULTICAST_ADDRESS_IPV4 : MULTICAST_ADDRESS_IPV6);
+    sockAddrSend_.setFamily(domain_);
+    sockAddrSend_.setAddress(domain_ == AF_INET ? MULTICAST_ADDRESS_IPV4 : MULTICAST_ADDRESS_IPV6);
     sockAddrSend_.setPort(port_);
 
     //Setup for send data
@@ -277,10 +270,10 @@ PeerDiscovery::listener_thread(PeerDiscoveredCallback callback)
             size_t data_receive_size = data_receive.size();
             auto from = recvFrom(data_receive.data(), data_receive_size);
 
-            //Data_receive_size as a value-result member will hlep to filter packs 
-            if(data_receive_size != data_receive.size()){ 
+            //Data_receive_size as a value-result member will hlep to filter packs
+            if(data_receive_size != data_receive.size()){
                 perror("Data Received Unmatch");
-                continue; 
+                continue;
             }
 
             std::array<uint8_t,dht::InfoHash::size()> data_infohash;
@@ -330,7 +323,6 @@ PeerDiscovery::stop()
     }
     cv_.notify_one();
     if (stop_writefd_ != -1) {
-
         if (write(stop_writefd_, "\0", 1) == -1) {
             perror("write");
         }
diff --git a/src/utils.cpp b/src/utils.cpp
index d5c55049ba88ab831232b09353e55d911cfb3501..144bc48bd86a8a30abe741a1507d515c794b5a26 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -73,19 +73,23 @@ SockAddr::resolve(const std::string& host, const std::string& service)
     return ips;
 }
 
-
-SockAddr
-SockAddr::parse(sa_family_t family, const char* address)
+void
+SockAddr::setAddress(const char* address)
 {
-    SockAddr addr;
-    addr.setFamily(family);
-    if (inet_pton(family, address, family == AF_INET ? (void*)&addr.getIPv4().sin_addr.s_addr : (void*)&addr.getIPv6().sin6_addr) <= 0){
-        throw std::runtime_error("SockAddr::parse inet_pton");
+    auto family = getFamily();
+    void* addr = nullptr;
+    switch (family) {
+    case AF_INET:
+        addr = &getIPv4().sin_addr;
+        break;
+    case AF_INET6:
+        addr = &getIPv6().sin6_addr;
+        break;
     }
-    return addr;
+    if (not addr or inet_pton(family, address, addr) <= 0)
+        throw std::runtime_error("Can't parse IP address");
 }
 
-
 std::string
 print_addr(const sockaddr* sa, socklen_t slen)
 {