![]() |
TClient/ServerSocket - Daten kommen nicht an.
Hallo,
brauche mal Hilfe von Experten. Habe einen Pool von Programmen, die mit TCP/IP auf ein und demselben Rechner untereinander kommunizieren. Das ist so, weil es ein sehr modulares System ist. Nun stellt sich folgendes Problem: Es gibt zwei Programme, die eine Verbindung haben (Socket ist connected), das eine Programm sendet einen string, aber er kommt auf der anderen Seite nicht an. Es treten aber keine Fehler auf - d.h. der Sender denkt es ist alles in Ordnung und der Empfänger wartet halt weiter und weiter und weiter.... Ich benutze Delphi5 und seine TClientSocket/TServerSocket Komponenten. Habt Ihr da schon mal was von gehört, bzw. einen Tip wo ich noch suchen kann ? Gruss Thomas |
Re: TClient/ServerSocket - Daten kommen nicht an.
wie wäre es, wenn du mal nen stück deines codes hier rein schreibst (das, was für senden/empfangen "verantwortlich" ist) - und dann schauen wir mal, was da vll falsch ist oder wie auch immer...
Ciao Tom |
Re: TClient/ServerSocket - Daten kommen nicht an.
Hi,
das kann ich zwar tun, doch bin ich mir sicher, dass da nichts falsch ist. Ich mach das schon was länger :-) Ich denke das liegt irgendwo am Betriebssystem und dachte da hätte jemand vllt. eine Idee, ob man da was trimmen kann. Gruss |
Re: TClient/ServerSocket - Daten kommen nicht an.
Schick doch einfach mal den Source ... oft schleichen sich Flüchtigkeitsfehler ein.
Florian |
Re: TClient/ServerSocket - Daten kommen nicht an.
Zitat:
Kommen Connectionfehler bei Aufbau der Verbindung, die dummerweise blind abgefangen werden? Gruß, Christoph |
Re: TClient/ServerSocket - Daten kommen nicht an.
Also, auf vielfachen Wunsch hier der Code....
Delphi-Quellcode:
Dies ist mein standard Paket für einen Client-Socket. Es funktioniert sehr gut. Es ist ja nicht so, dass ich einen grundsätlichen Fehler habe, sondern das Problem zeigt sich nur auf bestimmten System - und zwar solchen, die relativ viel IP Kommunikation betreiben.// Verbindung aufnehmen - wird durch einen Timer geprüft und evtl. aufgerufen. procedure TdmCommunication.ReconnectVQDB; begin VQDBSocket.Host := 'localhost'; VQDBSocket.Port := VQDB_port; // VQDBconnected := _connecting_; VQDBSocket.Open; end; // Ereignis Connect eingetreten. // Es wird eine Registrierung an die Serveranwendung gesendet. procedure TdmCommunication.VQDBSocketConnect(Sender: TObject; Socket: TCustomWinSocket); begin VQDBConnected := _connected_; Socket.SendText('PT|CM$$|RIDB,RE' + eorec); Logout('[VQDB] connected.'); // set keep alive option if setsockopt(Socket.SocketHandle, SOL_SOCKET, SO_KEEPALIVE, @bOptVal, bOptLen) = SOCKET_ERROR then Logout('Error, can not set socket options. ' + SysErrorMessage(WSAGetLastError())); end; // Ereignis Disconnet eingetreten. Timer wird den Connect wieder einleiten. procedure TdmCommunication.VQDBSocketDisconnect(Sender: TObject; Socket: TCustomWinSocket); begin VQDBConnected := _disconnected_; Logout('[VQDB] disconnected.'); end; // Error aufgetreten - Timer wird den Connect wieder einleiten. procedure TdmCommunication.VQDBSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); begin VQDBSocket.Close; VQDBConnected := _disconnected_; LogOut('[VQDB] socket error ' + IntToStr(ErrorCode) + ' ' + SysErrorMessage(ErrorCode)); Errorcode := 0; end; // Daten lesen und an den Buffer anhängen. // Es wird für die Lesende Task ein Ereignis ausgelöst zum abholen der Daten. procedure TdmCommunication.VQDBSocketRead(Sender: TObject; Socket: TCustomWinSocket); var s: string; begin s := ''; while Socket.ReceiveLength > 0 do s := s + Socket.ReceiveText; if Assigned(FOnVQDBDataAvailable) then begin FVQDBBuffer := FVQDBBuffer + s; FOnVQDBDataAvailable(self, length(FVQDBBuffer)); end else Logout('discarded: ' + s); end; Jetzt zum Servercode
Delphi-Quellcode:
Es sind ca 12-14 Programme die mehrfach auf diese Art und Weise kommunizieren. Sporadisch taucht nun der im ersten Post beschriebene Fehler auf - und auch nur auf Systemen einer gewissen Ausstattung.// Ein Client hat sich verbunden - Es wird zunächst nur die KEEPALIVE option gesetzt // weiteres geschieht im OnRead procedure TdmCommunication.ListenSocketClientConnect(Sender: TObject; Socket: TCustomWinSocket); begin // set keep alive option if setsockopt(Socket.SocketHandle, SOL_SOCKET, SO_KEEPALIVE, @bOptVal, bOptLen) = SOCKET_ERROR then Logout('Error, can not set socket options. ' + SysErrorMessage(WSAGetLastError())); end; // Client disconnected // DeleteClient löscht den Client aus der Verwaltungsliste. procedure TdmCommunication.ListenSocketClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); begin DeleteClient(Socket); end; // Daten vom Client angekommen. // Registrierung wird erkannt und dann in die Verwaltung eingereiht. // Wenn keine Registrierung dann werden die Daten in die Warteschlange gegeben. procedure TdmCommunication.ListenSocketClientRead(Sender: TObject; Socket: TCustomWinSocket); var s: string; begin s := ''; while Socket.ReceiveLength > 0 do s := s + Socket.ReceiveText; if CommSubStr(s, '|CM') = '$$' then // Anmeldung RegisterClient(Socket, s) else begin Logout('[Listen]: ' + TranslateCtrlChars(s)); if Assigned(FOnListenDataAvailable) then begin FListenBuffer := FListenBuffer + s; FOnListenDataAvailable(self, length(FListenBuffer)); end else Logout('discarded: ' + s); end; end; // Client error aufgetreten - Der Socket wird geschlossen... // Der Client wird aus der Verwaltung gelöscht. procedure TdmCommunication.ListenSocketClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); begin DeleteClient(Socket); LogOut('[Listen] socket error ' + IntToStr(ErrorCode) + ' ' + SysErrorMessage(ErrorCode)); ErrorCode := 0; end; // Löschen eines Client aus der Registrierungsliste. procedure TdmCommunication.DeleteClient(Socket: tCustomWinSocket); var i: integer; cs: tClientSession; begin for i := 0 to Clients.Count - 1 do begin cs := tClientSession(clients.Objects[i]); if cs.Socket = Socket then begin cs.Free; clients.Delete(i); break; end; end; end; // Einstellen eines Clients in die Registrierungsliste procedure TdmCommunication.RegisterClient(Socket: TCustomWinSocket; s: string); var aKennung: string; aSession: tClientSession; i: integer; begin Logout('register client: ' + s); aKennung := copy(s, 1, 2); i := clients.IndexOf(aKennung); if i >= 0 then // schon in der Liste, update recordlist with tClientSession(clients.objects[i]) do RecordList := CommSubStr(s, '|RI') else begin aSession := tClientSession.Create(Socket, aKennung); aSession.RecordList := CommSubStr(s, '|RI'); Clients.AddObject(aKennung, aSession); end; end; // Wenn Daten gesendet werden sollen, läuft diese Prozedur über die registrierten Clients, // prüft ob für diesen Client der zu sendende Datensatz gültig ist, // und wenn ja sendet die Daten. function TdmCommunication.SendToRegistered(const s: string): integer; var i: integer; cmd: string; begin result := 0; cmd := CommsubStr(s, '|CM'); for i := 0 to clients.Count - 1 do with tClientSession(clients.Objects[i]) do begin if pos(cmd, RecordList) > 0 then begin Logout('to ' + Kennung + ': ' + s); Socket.SendText(s); inc(result); // at least one client who did care about end; end; end; Jeder Tip willkommen. Gruss |
Re: TClient/ServerSocket - Daten kommen nicht an.
Zitat:
tja wenn das so einfach wäre. Wie der Code zeigt wird jeder Fehler mit der Prozedur Logout protokolliert. Firewall gibt es nicht auf dem System. Ist übrigens Win2k Server. Der Verbindungsaufbau klappt. Interessant ist, dass die Kommunikation am Anfag läuft und erst später einfach aussetzt. Gruss |
Re: TClient/ServerSocket - Daten kommen nicht an.
Keiner mehr eine Idee ?
:gruebel: |
Re: TClient/ServerSocket - Daten kommen nicht an.
Hi,
'ne direkte Idee an der Stelle nicht, aber es ist sicher interessant heraus zu bekommen ob die Connection Kommentarlos verschwunden ist, oder die daten nicht in's Receive gelangen. Versuch doch mal die betroffenen Sockets vom Server aus anzusprechen. Ich würde dazu ein "Ping-Äquivalent" auf deinem Port schaffen, das dein Socket-server periodisch an alle connected-Clients sendet. Damit könntest Du dann erst mal folgendes prüfen: - ist die Clientconnection wirklich noch aktiv? - Wenn nicht, läßt sich eine Fehlermeldung generieren? - empfängt der Client den Server-Watch? - kann der Client darauf antworten -> ergo bekommt der Server darauf was zurück? Das währe aus meiner Sicht ein Procedere, das zumindest automatisch prüfen kann, ob noch alles ok ist. Passiert da nichts, disconnecten und neues Connect (Client-Seite?). In Bezug auf die Performance sicher nicht der Renner, aber was soll man machen. Gruß oki |
Re: TClient/ServerSocket - Daten kommen nicht an.
Hallo,
danke für den Tipp. In einer anderen Anwendung hab ich genau das auch schon gemacht - ich hielt es aber ausschließlich für einen Workaround. Ich bin eigentlich immer bestrebt zu ergründen warum etwas so passiert - weil gedacht ist es sicher nicht so, also muss ich was falsch gemacht haben. Interessant an dieser Geschichte ist noch: Wenn ich diesen Zustand erreicht habe und ich schließe das Serverprogramm, erkennt der Client diese und meldet es. D.h. die Connection ist nicht vollständig weg, sondern nur die Daten gelangen nicht mehr in's Receive. Das dumme ist, dass wenn ich deine vorgeschlagene Prozedur einbaue, kann das Erkennen schon zu spät sein - es können bereits Daten in's Nirvana geschrieben worden sein. Muss ich mir also noch was dazu auf der Protokollseite einfallen lassen, dass das wiederholt werden kann. Gruss Thomas |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz