SocketError SocketImpl::bind(const SockAddr& sockAddr) { if (socket == INVALID_SOCKET) { return SocketError::NotInitialized; } sockaddr_storage storage; sockAddr.toNative(&storage); // For bind we also want to set the SO_EXCLUSIVEADDRUSE option DWORD opt = 1; int optRes = ::setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&opt, sizeof(DWORD)); if (optRes != 0) { return getSocketError(::WSAGetLastError()); } int bindRes = ::bind(socket, (const sockaddr*)&storage, sizeof(sockaddr_storage)); if (bindRes != 0) { return getSocketError(::WSAGetLastError()); } // And then we need to fetch back the bound addr/port int nameLen = sizeof(sockaddr_storage); int nameRes = ::getsockname(socket, (sockaddr*)&storage, &nameLen); if (nameRes != 0) { return getSocketError(::WSAGetLastError()); } localAddr = SockAddr::fromNative(&storage); return SocketError::Ok; }
SocketError SocketImpl::connect(const SockAddr& sockAddr) { if (socket == INVALID_SOCKET) { return SocketError::NotInitialized; } sockaddr_storage storage; sockAddr.toNative(&storage); // For reasons that I presume have to do with DisconnectEx, ConnectEx // requires a bound socket sockaddr_storage addrAny; addrAny.ss_family = storage.ss_family; INETADDR_SETANY((sockaddr*)&addrAny); int bindRes = ::bind(socket, (const sockaddr*)&addrAny, sizeof(sockaddr_storage)); if (bindRes != 0) { return getSocketError(::WSAGetLastError()); } SocketError res; connect_co(sockAddr, &res).get(); return res; }