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