GetAddrInfo: dynamischer Port



  • Hallo!
    Ich möchte meine bestehende Server/Client-Anwendung unabhängig von der Adressfamilie (konkret IPv4 und IPv6) machen und habe diesbezüglich ein paar Fragen.

    1. Ich nutze einen Socketpool, in dem alle Sockets z.B. mit IPv4 geladen wurden. Kann man die Adressfamilie des Sockets nachträglich ändern oder muss ich dann auf den Pool pfeifen und einen neuen Socket erstellen?

    2. Ich versuche mit ConnectEx Verbindungen zu Servern auf zu nehmen. ConnectEx verlangt jedoch, dass der Socket vorher an eine Adresse gebunden wird. Die Adressfamilie dafür entnehme ich per GetAddrInfo vom Server:

    // vereinfachtes Beispiel ohne Überprüfungen etc:
    std::string servername = get_name_from_anywhere(); // IPv4, IPv6 oder DNS-Adresse
    char* serverport = get_port_from_anywhere();
    addrinfo hints = { 0 }, *remote = 0, *local = 0;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    GetAddrInfo(servername.c_str(), serverport, &hints, &ai);
    // Jetzt hat ai die Informationen, nun muss der Socket erstellt gebunden werden
    SOCKET client_socket = WSASocket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
    // Gibt es sowas?:
    /*
    SOCKET client_socket = socketpool.get();
    set_af(client_socket, ai->ai_family);
    */
    hints.ai_family = ai->ai_family;
    hints.ai_flag = AI_PASSIVE;
    GetAddrInfo(0, "Was muss hier für einen dynamischer Port hin?", &hints, &local);
    bind(client_socket, local->ai_addr, local->ai_addrlen);
    // ... ConnectEx laden etc.
    // Endlich verbinden
    ConnectEx(client_socket, remote->ai_addr, remote->ai_addrlen, ...);
    

    Dass ich mit AI_PASSIVE angebe, dass der Socket gebunden werden soll, ist klar. Nur will GetAddrInfo trotzdem noch einen Parameter für den Service/Port, und ich kann in dem Moment nicht wissen, was Windows dem Programm für ein Port zuteilt. 😕



  • wie wäre es mit "0"?



  • Das endet mit WSAHOST_NOT_FOUND. 😞



  • und du bist dir sicher das der host auch eine IPv6 adresse besitzt ?

    und was meinst du mit dynamischer port ?

    wo steht das du den scoket vor Connectex binden musst ?

    warum verwendest du ueberhaup connectex ?

    Meep Meep



  • > und du bist dir sicher das der host auch eine IPv6 adresse besitzt ?

    Das sollte heut zu Tage eigentlich so sein. 🙂

    > und was meinst du mit dynamischer port ?

    Wenn man den Systemcall bind() auf Port 0 setzt, wird sich Windows einen Port innerhalb einer Range aussuchen.

    For TCP/IP, if the port is specified as zero, the service provider assigns a unique port to the application from the dynamic client port range. On Windows Vista and later, the dynamic client port range is with a value between 49152 and 65535. This is a change from Windows Server 2003 and earlier where the dynamic client port range was a value between 1025 and 5000.

    Nur, hier wird die Adresse nicht von mir, sondern von GetAddrInfo() vorbereitet.

    > wo steht das du den scoket vor Connectex binden musst ?

    s [in]

    A descriptor that identifies an unconnected, previously bound socket. See Remarks for more information.

    http://msdn.microsoft.com/en-us/library/ms737606(VS.85).aspx
    Wenn du es nicht tust gibt's Fehlermeldung. 🙂 Jeder Socket braucht eine Adresse, das Berkeley-connect() macht's implizit.

    > warum verwendest du ueberhaup connectex ?

    Ich brauche viele asynchrone Connect-Befehle gleichzeitig.



  • So, ich hab es jetzt etwas unschön gelöst, funktioniert jedoch. Nach dem Call von GetAddrInfo() ändere ich den Port in addrinfo::ai_addr manuell:

    if(ai->ai_family == AF_INET)
    			reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_port = htons(0);
    		else if(ai->ai_family == AF_INET6)
    			reinterpret_cast<sockaddr_in6*>(ai->ai_addr)->sin6_port = htons(0);
    		else
    			throw net_error("unknown address familiy specified");
    


  • Dann würde mich aber mal interessieren was GetAddrInfo für einen Port setzt wenn man "0" übergibt.
    Hast du auch schonmal NULL als Port ausprobiert?



  • Ich brauche viele asynchrone Connect-Befehle gleichzeitig.

    Wundere dich nicht wenn du auf das Half-Open Connection Limit stösst. 🙂



  • hallo

    ich hab nun mal selst einen connect ausprobiert. folgend funktioniert es:

    void SocketClient::Connect(int type, int protocol, sockaddr *addr, WSAPROTOCOL_INFO *info, GROUP g, DWORD flags)
    {
       addrinfo hints = {0};
       addrinfo *result;
    
       memset(&hints, 0, sizeof(hints));
       hints.ai_family   = addr->sa_family;
       hints.ai_socktype = type;
       hints.ai_protocol = protocol;
       hints.ai_flags    = AI_PASSIVE;
    
       char hostname[255];  
       ::gethostname(hostname, 255);
    
       int res = getaddrinfo(hostname, 0, &hints, &result);
       if(res != 0)
          throw ::WSAGetLastError();
    
       addrinfo *ptr;
       for(ptr = result; ptr != 0; ptr = ptr->ai_next)
       {
          Create(addr->sa_family, type, protocol, info, g, flags); // WSASocket
    
          if(m_sock == INVALID_SOCKET)
             continue;
    
          try
          {
             Bind(ptr->ai_addr); // bind
          }
          catch(...)
          {
             Close();
          }
    
          if(m_sock != INVALID_SOCKET)
             break;
       }
    
       ::freeaddrinfo(result);
    
       if(m_sock == INVALID_SOCKET)
          return;
    
       GUID connectex_guid = WSAID_CONNECTEX;
    
       DWORD bytes;
       if(::WSAIoctl(m_sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &connectex_guid, sizeof(connectex_guid), 
                     &overlapped.ConnectEx, sizeof(overlapped.ConnectEx), &bytes, 0, 0) == SOCKET_ERROR)
          throw ::WSAGetLastError();
    
       overlapped.ConnectEx(m_sock, addr, SockAddrLen(addr), 0, 0, 0, &overlapped.overlapped);
    }
    

    'addr' welche der funktion uebergeben wird, ist die sockaddr des zu verbindenden servers.
    vielleicht hilts dir ja weiter.

    Meep Meep



  • Nö, bei mir bedankt sich dann GetQueuedCompletionStatus mit ERROR_INVALID_NETNAME.



  • hi

    koenntest du mal deinen client source posten ? oder ihn mir mal schicken ?
    arbeite auch grad an IOCP und hab da noch so meine problemchen was das vertehen betrifft. vielleicht koennen wir uns da gemeinsam weiter helfen

    Meep Meep



  • Kann ich morgen machen. 😉


Anmelden zum Antworten