UDP Nachricht geht flötten



  • Hallo zusammen,

    ich habe folgendes kleines Problem. Ich habe eine Client Server Anwendung. Alle Clients melden sich am Server an und gehen dann in ne Wartestellung. Der Server sagt dann irgendwann mal los (wenn alle da sind). Nun bemerken komischer Weise nicht alle Clients das los. Folgendes Beispiel:

    1 Server, 2 Clients:

    Server:
    Melde Client Addresse 1 Port 1 an
    Melde Client Addresse 1 Port 2 an
    ...
    los

    Client 1:
    Anmelden am Server.
    Warten ...
    Empfange los, mache los ...

    Client 2:
    Anmelden am Server.
    Warten ... ...............

    wo ist das Problem? Die liste in der ich mir beim Server die Clients merke gehe ich richtig durch. Hier noch ein bissl Code vom Server:

    /**
     * This function tells a client, that it can continue to work or that the end of the simulation is reached.
     *
     * @param ip is the address of the client which should be notified
     */
    void LifeServer::notify(IPAddress* ip, bool flag){
    
      network->ack(ip, flag);
    
    }//End notify
    
    /**
     * The more general notify, which sends the same notification to all clients.
     */
    void LifeServer::notifyAll(bool flag){  
    
      for(unsigned i=0; i < clients.size(); i++){
    
        notify(clients.at(i),flag);
    
      }//End for 
    
    }//End notifyAll
    
    wobei network (vom Typ ServerToUDPNetwork) dies macht: 
    
    void ServerToUDPNetwork::ack(Client* client, bool end) {
    
      //create message	
      Message msg;
    
      msg.type = Ack;
      msg.data.ack.end = end;
    std::cout << "send barrier to ADDR: " << client->getAddr() << " PORT: " << client->getPort() << "\n";  
      //send message
      network->reply(*client, &msg, sizeof(msg));
    
    } //ack
    

    der Client wartet auf notify mittels:

    bool ClientToUDPNetwork::barrier(int seq) {
    
      //create message
      Message s_msg;
      Message r_msg;
      s_msg.type = BarrReq;
      s_msg.data.barr_req.seq = seq;
    
      //send message
      network->request(*server, (void*) &s_msg, sizeof(s_msg), (void*) &r_msg, sizeof(r_msg),0);
    
      //evaluate recieved message
      if (r_msg.type == Ack) {
    std::cout << "BARRIER RECEIVE ACK\n";
        return r_msg.data.ack.end;
    
      }//End if
    
      return false;
    
    }//End barrier
    

    Sieht jemand eine Fehler oder hat einen Tip??? Danke schon mal.



  • UDP Nachricht geht flötten

    das ist doch was ganz normales bei UDP?!



  • Richtig. Also entweder selbst Mechanismen einbauen, die den Nachrichtenverlust ausgleichen bzw. abfangen können oder auf TCP setzen.



  • Also wenn du nicht Massendaten überträgst, bei denen es egal ist ob da mal ein Frame verloren geht, weil es einfach schnell gehen muss (z.B. Videos per Netzwerk/Internet gucken) solltest du auf TCP setzen. Wenn es aber ein Messenger ist, sollte schon sichergestellt sein, dass die Nachrichten auch ankommen.
    Ansonsten solltest du zumindest nen Retry nach einem gewissen Timeout ohne Antwort einbauen.

    Greetz



  • hallo,

    das ist nicht gerade hilfreich. ich muß UDP nutzen, von daher ist der hinweis auf TCP obsolet. außerdem ist es ja nicht so das irgendeine nachricht verloren geht, sondern immer die eine, wie beschrieben und immer beim selben client. von daher glaube ich nicht das udp an sich schuld daran ist. gibt es ernsthafte kommentare? ausserdem habe ich ne einfache set/get semantik, was nicht gerade auf TCP passt, in dem sinne es entworfen wurde.

    mfg



  • Erstmal waren das ernsthafte Kommentare. Wenn du Hilfe willst musst du auch mehr Infos liefern, als nur zu sagen das läuft nicht und ein Client reagiert nicht mehr. Wenn man dann UDP sieht, ist meistens die erste Annahme das UDP daran schuld sein kann. Man kann nur so viel Hilfe erwarten wie man den anderen Informationen gibt und da diese sehr spärlich sind/waren kannst du auch nicht auf mehr und bessere Informationen warten.

    Des Weiteren geht aus dem ersten Text nichts daraus hervor das du unbedingt UDP benutzen musst/willst, noch das es immer bei dem Client passiert. Wie sonst gesagt, versuchs mal mit einem Timeout und sende eventuell nochmal eine Anfrage an den Server (sofern man das entsprechend umbauen kann).

    Aber mal zu den beiden Clients. Laufen die auf dem gleichen System? Wenn ja, versuch mal zwei unterschiedliche Systeme. Startest du immer nur 2 Clients? Was passiert bei mehr als 2 Clients (sofern mehr als 2 möglich sind), geht nur der zweite flöten oder auch nachfolgende?

    Des Weiteren ist es bissl schwer da zu helfen, der Fehler kann schon ganz woanders erzeugt werden. Also braucht man eventuell mehr Code. Netzwerkanwendungen sind nicht unbedingt leicht zu debuggen. Dazu ist noch die Frage welche Netzwerk-API du verwendest, sieht nicht danach aus als ob du auf die POSIX-Socket-Funktionen zugreifst.

    Greetz



  • ok ok, ihr habt recht. also udp ist pflicht. das komische an dem fehler war das ich das timeout hochgesetzt hatte, ein retransmit der nachricht angestoßen hatte und auch die nachricht immer nicht ankam. ich habe es lokal getestet, auch bei mehr clients als zwei gab es immer ein / zwei die die nachricht nicht mitbekommen haben. ich habe das jetzt so umgebaut das ich einfach die antwort auf die anmeldung solange verzögere bis alle da sind und dann die einzelnen infos rausschicke. so gehts.

    zu tcp, das ist die nächste aufgabe, also werde ich noch mal auf euch zurück kommen. ich danke 🙂

    gruß und dank


Anmelden zum Antworten