Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   (C++) Client/Server-Sendeprobleme (https://www.delphipraxis.net/163496-c-client-server-sendeprobleme.html)

LukeSkywalker 30. Sep 2011 15:44

(C++) Client/Server-Sendeprobleme
 
Hallo,
ich spiele mich gerade mit einem Client/Server-Projekt (C++ Builder 6), dass mir im wesentlichen ermöglichen soll, an andere Benutzer im Netzwerk Nachrichten zu senden, die als Message-Box erscheinen (nein, kein net send).
Nun fände ich es äußerst praktisch, wenn sich die einzelnen Rechner zu meinem Rechner verbinden, sodass ich bei Bedarf immer eine Liste der aktuell im Netzwerk eingeloggten Benutzer habe.

Soweit funktioniert das ganze recht gut. Ich habe eine TListBox auf einem Form, in dem nach und nach die Computer eingetragen werden:
Code:
void __fastcall TForm3::ServerSocket1ClientConnect(TObject *Sender,
      TCustomWinSocket *Socket)
{
        if(ListBox1->Items->IndexOf(Socket->RemoteAddress) == -1)
                ListBox1->Items->Add(Socket->RemoteAddress);
}
Auf der Client-Seite läuft das ganze recht ähnlich. Um allerdings Fehlermeldungen zu umgehen, falls mein Rechner partout nicht verfügbar sein sollte, versucht der Client in einer Dauerschleife (TTimer) eine Verbindung zu mir herzustellen:
Code:
void __fastcall NetMessageTimer::Timer1Timer(TObject *Sender) {
        try {
                if(!Connected) {
                        ClientSocket1->Close();
                        ClientSocket1->Open();
                }
        } catch(...) {
                //ShowMessage(err.Message);
        }
}

void __fastcall NetMessageClass::ClientSocket1Error(TObject *Sender,
      TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
        // Fehler ignorieren
        ErrorCode = 0;
}

void __fastcall NetMessageClass::ClientSocket1Connect(TObject *Sender,
      TCustomWinSocket *Socket)
{
        Connected = true;
        //Timer1->Enabled = false;
}

void __fastcall NetMessageClass::ClientSocket1Disconnect(TObject *Sender,
      TCustomWinSocket *Socket)
{
        Connected = false;
        //Timer1->Enabled = true;
}

WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
        // Erstellen der benötigten Komponenten
        NetMessageClass *srv = new NetMessageClass();
        NetMessageTimer *tmr = new NetMessageTimer();
        TMsg *msgRec = new TMsg();
        ClientSocket1 = new TClientSocket(NULL);
        Timer1 = new TTimer(NULL);

        // Events zuweisen
        ClientSocket1->OnConnect = srv->ClientSocket1Connect;
        ClientSocket1->OnDisconnect = srv->ClientSocket1Disconnect;
        ClientSocket1->OnError = srv->ClientSocket1Error;
        ClientSocket1->OnRead = srv->ClientSocket1Read;
        Timer1->OnTimer = tmr->Timer1Timer;

        // Den Client starten
        Timer1->Enabled = true;

        do {
                //Application->ProcessMessages();
                if(PeekMessage(msgRec,0,0,0,PM_REMOVE)) {
                        DispatchMessage(msgRec);
                } else {
                        WaitMessage();
                }
        } while(msgRec->message != WM_QUIT || msgRec->message != WM_CLOSE);
}
Tatsächlich erscheinen auch nach und nach die IP-Adressen in der ListBox (es sei denn, der Computer schaltet in den Standby-Modus und wird wieder eingeschaltet - gibt es eine Möglichkeit dann die Verbindung nochmals herzustellen?).

Das Problem ist vielmehr das Versenden der Nachricht. Klicke ich auf einen Button, soll der ausgewählten IP-Adresse eine Nachricht (Edit1->Text) zugesendet werden. Die Nachricht wird zwar abgesendet, kommt bei der Gegenstelle allerdings nur in 60% der Fälle an - ansonsten erhalte ich nicht einmal eine Fehlermeldung - interessant ist, dass es nach mehrmaligem Neustarten der Serveranwendung wieder funktioniert (bis auf einige Male, wo sich der ClientSocket selbst abschaltet - der Prozess wird zwar weiterhin im Taskmanager angezeigt, allerdings scheint die IP-Adresse nicht mehr in meiner Liste auf).

Ich vermute, dass es damit zu tun haben könnte, dass beim Neustart des Servers die Resourcen am Client nicht freigegeben werden (netstat zeigt mir eine ganze Liste an Verbindungen an, die aufs schließen warten). Irgendeine Idee, warum es nicht so funktioniert, wie es soll?

Hier ist noch der Code der Versende-Routine:
Code:
void __fastcall TForm3::Button2Click(TObject *Sender)
{
        if(ListBox1->ItemIndex >= 0) {
                for(int i=0;i<ServerSocket1->Socket->ActiveConnections;i++) {
                        if(ServerSocket1->Socket->Connections[i]->RemoteAddress == ListBox1->Items->Strings[ListBox1->ItemIndex]) {
                                ServerSocket1->Socket->Connections[i]->SendText(Edit1->Text);
                                break;
                        }
                }
        }
}
.. und der Empfangs-Routine:
Code:
void __fastcall Client::ClientSocket1Read(TObject *sender, TCustomWinSocket *socket)
{
      ShowMessage(socket->ReceiveText());
}
Wie gesagt, über Hilfe wäre ich dankbar, da ich mittlerweile schon seit geraumer Zeit versuche, das Problem zu lösen.

mfg

Robotiker 1. Okt 2011 12:11

AW: (C++) Client/Server-Sendeprobleme
 
Kann man so überhaupt mit der VCL arbeiten ?

Das ist nicht die normale vom C++ Builder generierte Projektstruktur. Die Erzeugung des Application Objektes ist aus dem WinMain entfernt worden und eine eigene Messageloop eingebaut worden. Trotzdem funktionieren die Formulare ?

Außerdem habe ich noch nie gesehen, dass man Komponenten in dieser Form global in der WinMain erzeugt.

Denke mal das beschriebene Verhalten hat weniger mit den Sockets zu tun, als das da "quer zum Design der VCL" programmiert wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:51 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz