Winsock-bind() nicht mit WSAEADDRNOTAVAIL für die gerichtete broadcast-Adresse

Ich bin einrichten einen UDP-socket und versucht zu binden, was sollte eine gültige Netzwerk-broadcast-Adresse, es (192.168.202.255 : 23456), aber bind schlägt fehl mit Fehler 10049, WSAEADDRNOTAVAIL. Wenn ich einen localhost broadcast-Adresse, 127.0.0.255, gelingt es.

WSAEADDRNOTAVAIL's-Dokumentation sagt, dass "Die angeforderte Adresse ist in diesem Kontext ungültig. Diese Regel Ergebnisse aus einem Versuch zum binden an eine Adresse, die nicht gültig für den lokalen computer. Dies kann auch die Folge von zu verbinden, sendto, WSAConnect WSAJoinLeaf oder WSASendTo, wenn der remote-Adresse oder der port ist nicht gültig für einen Remotecomputer (Z. B. Adresse oder port 0)." Aber ich denke diese Adresse, 192.168.202.255, sollte eine gültige broadcast-Adresse, da der folgende Eintrag beim laufen ipconfig:

Winsock-bind() nicht mit WSAEADDRNOTAVAIL für die gerichtete broadcast-Adresse

Was das problem sein könnte?

Code

Ich bin neu auf Winsock-Programmierung und bin wahrscheinlich machen Sie einen elementaren Fehler, aber ich kann es nicht finden. Den code habe ich bisher:

m_ulAddress = ParseIPAddress(strAddress);
//Winsock 2.2 is supported in XP
const WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA oWSAData;
const int iError = WSAStartup(wVersionRequested, &oWSAData);
if (iError != 0) {
    PrintLine(L"Error starting the network connection: WSAStartup error " + IntToStr(iError));
} else if (LOBYTE(oWSAData.wVersion) != 2 || HIBYTE(oWSAData.wVersion) != 2) {
    PrintLine(L"Error finding version 2.2 of Winsock; got version " + IntToStr(LOBYTE(oWSAData.wVersion)) + L"." + IntToStr(HIBYTE(oWSAData.wVersion)));
} else {
    m_oSocket = socket(AF_INET, SOCK_DGRAM /*UDP*/, IPPROTO_UDP);
    if (m_oSocket == INVALID_SOCKET) {
        PrintLine(L"Error creating the network socket");
    } else {
        //Socket needs to be able to send broadcast messages
        int iBroadcast = true; //docs say int sized, but boolean values
        if (setsockopt(m_oSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&iBroadcast, sizeof(iBroadcast)) != 0) {
            PrintLine(L"Error setting socket to allow broadcast addresses; error " + IntToStr(WSAGetLastError()));
        } else {
            m_oServer.sin_family = AF_INET;
            m_oServer.sin_port = m_iPort;
            m_oServer.sin_addr.S_un.S_addr = m_ulAddress;

            //!!! This is the failing call
            if (bind(m_oSocket, (sockaddr*)&m_oServer, sizeof(m_oServer)) == -1) {
                PrintLine(L"Error binding address " + String(strAddress.c_str()) + L":" + IntToStr(m_iPort) + L" to socket; error " + IntToStr(WSAGetLastError()));
            } else {
                m_bInitialisedOk = true;
            }
        }
    }
}

Kommentare

ParseIPAddress ist ein wrapper um inet_addr; Prüfung der Wert der m_oServer.sin_addr.S_un.S_addr es richtig zu sein scheint. m_oSocket ist ein SOCKET. Ich habe den Aufruf setsockopt da kann man keine Sendung über nichts, aber TCP standardmäßig (siehe zweiten Absatz in sendto's Bemerkungen); dieser Aufruf macht keinen Unterschied. PrintLine ist ein wrapper für die console-Ausgabe. Die ungeraden String /c_str() wirft konvertieren zu und von C++ wstrings um VCL Unicode-strings, da ich mich mit C++ Builder und dessen VCL-Bibliotheken. Die IP-Adresse ist eine schmale (char) string.

Den sendto - Dokumentation besagt, dass "Wenn ein socket geöffnet wird, einen setsockopt-Aufruf gemacht wird, und dann einem sendto-Aufruf gemacht wird, ist Windows-Sockets führt eine implizite bind-Funktion aufrufen." Dies impliziert, dass bind ist überhaupt nicht notwendig. Wenn ich das weglasse, die rufen, dann ruft sendto etwa so:

const int iLengthBytes = strMessage.length() * sizeof(char); //Narrow string
    const int iSentBytes = sendto(m_oSocket, strMessage.c_str(), iLengthBytes, 0, (sockaddr*)&m_oServer, sizeof(m_oServer));
    if (iSentBytes != iLengthBytes) {
        PrintLine(L"Error sending network message; error: " + IntToStr(WSAGetLastError()));

schlägt fehl mit Fehler 10047, ALS, "Address family not supported by protocol family."

Die Ausgabe von netsh winsock show catalog (bereits an der Unterseite von socket's Bemerkung) ist langwierig, aber enthält auch mehrere Einträge zu erwähnen, UDP und IPv4.

Eine mögliche Komplikation ist, dass diese läuft in einer VMWare Fusion host; Fusion macht eine ungerade setup für Netzwerke. Ich habe auch einen Cisco-VPN konfiguriert läuft zurück in mein Büro. Anschließen und trennen das macht keinen Unterschied.

Einer Sache scheint vertrackt zu mir ist schwer-casting des SOCKET m_oSocket zu sockaddr, aber das scheint normal zu sein-Praxis für Winsock-Programmierung, als ich gelesen habe Beispiele. Lesen es kann erforderlich sein, da die zu Grunde liegenden interpretation hängt von der Protokoll-Familie. Es scheint eine mögliche Fehlerquelle, aber ich bin mir nicht sicher, wie es zu vermeiden.

Irgendwelche Ideen? Ich bin ratlos 🙂

Setup

  • Windows 7 Pro unter VMWare Fusion 4.1.3
  • Das Programm kompiliert wird als 32-bit mit Embarcadero C++ Builder 2010.
  • Das Programm ist ein Konsolenprogramm nur
InformationsquelleAutor David | 2013-01-08
Schreibe einen Kommentar