Was steckt hinter den Casyncsocket Assertion -Problemen und den "unsachgemäßen Argumentationsfehlern" in meinem Code für MFC -Sockets?

StackOverflow https://stackoverflow.com/questions/800734

  •  03-07-2019
  •  | 
  •  

Frage

Ich wurde gebeten, einen Code für einen Freund anzusehen. (Ich zögerte zu Recht aufgrund des MFC und viel schlechter Code, aber er hat gewonnen ...)

Dies ist eine Dialogfeld -basierte Anwendung, die a verwendet CAsyncSocket.

Das Problem manifestiert sich in einigen Nonstop -Debugbreaks und anderen ähnlichen Dingen - es gibt auch ein Problem mit einem MFC ENSURE() Makro - Überprüfen der Socket auf Nullheit. Alle Probleme treten tief in MFC auf.

Einige Googeln haben mögliche Ressourcenlecks angezeigt, wenn man Themen in Vista/XP verwendet, aber ich denke nicht, dass dies das Problem hier ist.

Der Code ist basierend auf meinen paar Stunden des Debuggens ziemlich schlecht, aber im Grunde geht es darum: Folgendes:

(Wenn die Verbindung hergestellt wird, gibt es kein Problem - es ist nur der Fall, wenn keine Verbindung)

  • Anrufe Connect (Server, Socket) (auf dem abgeleiteten CAsyncSocket Objekt)
  • In dem OnConnect() Wir werden mitgeteilt, dass die Verbindung nicht funktioniert/nicht verbunden ist.
  • In einem Fenster -Timer für das Hauptdialog/die Hauptdialogie/die App befindet sich ein Timer. Wenn das Timer -Ereignis/der Handler aufgerufen wird, überprüfen wir, ob sie verbunden sind.
  • Wenn wir festgestellt haben, dass wir nicht verbunden sind (die OnConnect() war nicht gut) dann rufen wir an CAsyncSocket::Close(), Dann ruf an CAsyncSocket::Create() (ohne Parameter) Dann rufen Sie an CAsyncSocket::Connect(server, port)

Beachten Sie, dass der erste Anruf an Connect() hatte keinen vorhergehenden Anruf bei Create().

Meine erste wirkliche Frage:

  • Was ist der Unterschied zwischen den beiden und warum ist das? Create() erforderlich? (Wenn ich das entferne, stürzt es nicht mehr ab, aber ich verbinde mich auch nicht, wenn ich die Konnektivität wiederherstellt)

Die allgemeine Frage:

  • Was genau ist mit der Gestaltung des obigen Codes los?
  • Wie soll das im Allgemeinen funktionieren?

BEARBEITEN:

Ich habe den Code so behoben, dass alle Pfade anrufen Create() dann Connect().

Ich habe immer noch ein Problem mit einem Assert in CAsyncSocket::DoCallBack() - Die letzte Zeile des folgenden Codes gilt:

void PASCAL CAsyncSocket::DoCallBack(WPARAM wParam, LPARAM lParam)
{
    if (wParam == 0 && lParam == 0)
        return;

    // Has the socket be closed - lookup in dead handle list
    CAsyncSocket* pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, TRUE);

    // If yes ignore message
    if (pSocket != NULL)
        return;

    pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, FALSE);
    if (pSocket == NULL)
    {
        // Must be in the middle of an Accept call
        pSocket = CAsyncSocket::LookupHandle(INVALID_SOCKET, FALSE);
        ENSURE(pSocket != NULL);

Wenn ich das durchschreite, bekomme ich das Nachrichtenfeld: "Begegnet ein unsachgemäßer Argument"

Ich denke (aber bin mir nicht sicher), dass MFC versucht, den Sockel zurückzurufen, nachdem ich ihn geschlossen habe. Es befindet sich in einer Rückrufmethode (DoCallback()) Aber ich habe schon angerufen Close() auf der Steckdose.

Es sieht also wie ein MFC -Problem aus, es sei denn, ich soll zuerst abbestellen.

War es hilfreich?

Lösung

Ihre Wahl wirklich. Wenn Sie der Meinung sind, dass Sie mit einer anderen Sockets mehr Glück haben, dann tun Sie dies.

Microsoft hat jedoch viele Entwickler (und ich glaube, einige von ihnen sind vielleicht sogar gute). Sie können gerade kann, möchte die Möglichkeit berücksichtigen, dass der Fehler nicht alle am Ende liegt.

Die Menge an Hilfe, die Sie für ihre APIs und Produkte erhalten können, ist meiner Meinung nach auch gut.

Wenn Sie sich die Zeit nehmen würden, das MFC -Modell zu verstehen, würden Sie diesen "Aha" -Moment bekommen und es besser verstehen. Ich bin kein Fan von Winsock - ich bin eher an die Unix -Welt gewöhnt, in der Synchronisation der richtige Weg war, und Sie haben nur separate Prozesse/Threads durchgeführt, wenn Sie ein asynchronisiertes Verhalten haben möchten.

Ich vermute, Casyncsocket ist immer noch durch die Tatsache, dass MFC ein einsthreades Modell ist (in Bezug auf die GUI), obwohl Windows seit einiger Zeit echte präventive Threads veranstaltet. [Ich kann mich in diesem Beind -Kommentar irren, es ist schon eine Weile her, seit ich Win32 direkt verwendet habe].


Aktualisieren:

Basierend auf Ihrem Update, in dem Sie angegeben haben, was Sie getan haben, bin ich mir ziemlich sicher, dass Sie vor dem Erstellen keine Verbindung herstellen dürfen. Zitieren http://msdn.microsoft.com/en-us/library/3d46645f(vs.80).aspx,

Um ein Casyncsocket -Objekt zu verwenden, rufen Sie seinen Konstruktor auf und rufen Sie die Funktion erstellen, um das zugrunde liegende Socket -Handle zu erstellen ... und rufen Sie für einen Client -Socket die Funktion Connect -Mitglied auf.

Ich denke, dies ist eine zusätzliche Komplexität, da Windows in einer Ereignisumgebung asynchronen Sockets durchführen muss, da sie den Haupt-GUI-Thread nicht blockieren können.

In Unixy -Umgebungen gibt es entweder keinen Ereignis -Thread (normale Prozesse) oder Netzwerk -OPs werden nur manuell zu einem anderen Thread (in GUI -Apps) ausgebaut.

Dies war höchstwahrscheinlich eine Entwurfsentscheidung in Winsock vor langer Eine Art asynchronisiertes Verhalten, bei dem Nachrichten gepumpt werden, nutzte es immer, zu verwenden select() oder Themen/Prozesse].


Weiteres Update:

Diese Behauptung (keine Ausnahme) tritt normalerweise auf, wenn Sie das Socket -Objekt geschlossen und/oder gelöscht haben, während ein anhängiger Betrieb anhängig ist. In Ihrem Fall würde ich vorschlagen, dass es immer noch versucht, die Verbindung herzustellen, wenn Sie sie schließen.

Wenn dann die Verbindung erfolgreich ist oder fehlschlägt, wird der Rückruf aufgerufen und Ihre Steckdose nicht in den Tischen finden.

Dies ist kein MFC -Problem, es ist der Code Ihres Freundes, der gegen den Vertrag verstößt. Wenn Sie eine Verbindung (oder einen asynchronen Betrieb) durchführen, müssen Sie Warten Für den Erfolg oder Misserfolg vor dem Schließen des Socket (oder weiter daran arbeiten) - in diesem Fall bedeutet dies, dass Sie auf den Aufruf Ihrer Onconnect () -Funktion warten.

Aus dem Speicher rufst du das an create() Wenn Sie den asynchronen Socket erstellen, geschieht alles andere als Antwort auf Nachrichten, die in der Nachrichtenwarteschlange ankommen (dh Anrufe an Ihre OnXXX() Funktionen). Wie bei allen Win32 -GUI -Dingen sollen die Nachrichten das Programm vorantreiben (der Code wird als Antwort auf Nachrichten ausgeführt). Dieser Code sieht immer mehr wie klassischer Codierung aus, bei dem das Programm alles treibt - auf diese Weise den Wahnsinn, wie Sie Ihr Programm und den asynchronen Socket 'Thread' kämpft, um die Kontrolle zu kämpfen.

Ich habe es mir eine ganze Weile nicht mehr angesehen, aber Sie sollten in der Lage sein, ein Chatsrvr -Beispielprogramm in die Hände zu bekommen, das Ihnen zeigt, wie es geht.

Andere Tipps

Das Problem ist wahrscheinlich schlecht geschriebener Code und es besteht eine gute Chance, dass es wenig oder nichts mit MFC zu tun hat. Aber es ist schwer zu sagen aus Ihrer Beschreibung, die auf "Ich habe eine MFC -Anwendung, die alle möglichen Debug -Behauptungen wirft. Was soll ich tun?".

Es mag sein, dass ein Umschreiben in Ordnung ist, aber niemand kann wirklich sagen, ohne mehr über die Anwendung zu wissen. Ich denke, Sie (oder Ihr Freund) müssen diese Entschlossenheit treffen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top