![]() |
Daten per TCP/IP übertragen
Hallo zusammen,
ich hab mittlerweile schon vieles probiert, aber irgendwie knallt alles immer. In manchen Threads ließt man, die Komponenten sind mist, in anderen das andere Mist sind. Ich suche eigentlich eine Möglichkeit für einen kleinen TCP-IP Server und Client. Ein Client soll einen Connect auf einen Server machen und dann Daten dahin verschicken. Der Server soll die Daten einfach annehmen. Zusätzlich soll der Server auch an das Client Daten schicken können. Das Client ist eine Consolenanwendung. Soweit, ... soeinfach... Spätestens, wenn mein Client anfängt sehr schnell, viele Daten zu schicken, knallt es. Es scheint es so zu sein, als wenn der Send Befehl vom TCPClient sofort zurückkommt, ohne das er die Daten schon übertragen hat. Mache ich das jetzt 100 mal, dann kommt die Meldung "Buffer voll". Ein Sleep(1000) behebt das Problem lokal, aber wohl kaum im Netz. Ich habe wirklich schon viele Sachen ausprobiert, aber nix klappt. Bei manchen knallt es, sobald ein zweiten Client connected, andere knallen sofort. Ich hätte am liebsten was ohne irgendwelche Komponenten, direkt auf der winsock2 basierend. Hat jemand ein vlt sowas schonmal gemacht, oder ein HowTo? Vielen Dank für jeden Tip. Oliver |
Re: Daten per TCP/IP übertragen
Schau dir mal
![]() |
Re: Daten per TCP/IP übertragen
Wie sendest/empfängst du denn?
|
Re: Daten per TCP/IP übertragen
Hallo,
wenns schon "knallt" dann solltest du uns wenigstens ein bisschen Anteil haben lassen an deinem Feuerwerk. Glaubst du im ernst dass dir jemand helfen kann wenn du nur mitteilst "es knallt". Also: wo ist dein Sourcecode? Wie versuchst du Daten zu übertragen? Wie ist die Fehlermeldung? Was geht eigentlich schief? Grüsse Rainer |
Re: Daten per TCP/IP übertragen
Zitat:
Ich hab auch nix zur Zeit was überhaupt noch funktioniert. Da ich mitterweile so viel probiert habe, und alles ging schief, bin ich auf der Suche nach einem HowTo, wie man es richtig macht. Wenns dann noch immer "knallt" poste ich bestimmt auch den Code. Mir fehlt halt das wie und das warum es so funktioniert. Das mit dem Senden hat eigentlich immer funktioniert, aber das Empfangen halt nicht. Die Client Sende funktion sieht so aus:
Delphi-Quellcode:
Die WinSock2.pas ist eine Umsetzung der Jedis aus dem Jahr 2000 von der Winsock.h.
function TiBTcpClient.Send(const ABuffer; ALength: Integer): Integer;
var LSent: Integer; LCount: Integer; LLeft: Integer; LBuffer: Pointer; begin if not FConnected then raise Exception.Create('iBNoConnectionError'); LSent := 0; LLeft := ALength; try while LSent < ALength do begin LBuffer := Pointer(Integer(Pointer(@ABuffer)) + LSent); LCount := WinSock2.Send(FSocket, LBuffer^, LLeft, 0); if LCount = SOCKET_ERROR then RaiseLastSocketError; LSent := LSent + LCount; LLeft := ALength - LSent; end; except Reset; raise; end; Result := LSent; end; Zum Senden des Pakets habe ich mir eine Funktion geschrieben:
Delphi-Quellcode:
Empfangen tu ich das ganze mit den Indy Tools via:
function TiBTcpClient.SendStream(aStream: TStream; aSize: Integer): Integer;
var vMem: TiBMemoryStream; begin vMem := TiBMemoryStream.Create; try vMem.WriteCardinal(1); vMem.WriteCardinal(aSize); vMem.CopyFrom(aStream, aSize); result := Send(vMem.Memory^, vMem.Size); finally vMem.Free; end; end;
Delphi-Quellcode:
Teilweise kommen System out of resource Meldungen, dann gehts wieder. Meistens hängt das Programm aber beim Execute.
procedure TMainUnit.IdTCPServer1Execute(AContext: TIdContext);
type TPacketHeader = packed record PacketType: Cardinal; PacketSize: Cardinal; end; const cBuffSize = 1024; var vPacketHeader: TPacketHeader; vBytesToRead: Cardinal; LBuffer: Pointer; vBuffer: TBytes; vData: TiBMemoryStream; begin // Copy packet header vPacketHeader.PacketType := AContext.Connection.Socket.ReadCardinal(False); vPacketHeader.PacketSize := AContext.Connection.Socket.ReadCardinal(False); // Copy packet body vData := TiBMemoryStream.Create; while vPacketHeader.PacketSize > 0 do begin if vPacketHeader.PacketSize > cBuffSize then vBytesToRead := cBuffSize else vBytesToRead := vPacketHeader.PacketSize; AContext.Connection.Socket.ReadBytes(vBuffer, vBytesToRead, False); vData.Write(vBuffer[0], vBytesToRead); Dec(vPacketHeader.PacketSize, vBytesToRead); end; vData.Position := 0; // Verarbeite Block ... vData.Free; // Write tcp answer vBuffer := RawToBytes('OK', Length('OK')); AContext.Connection.Socket.Write(vBuffer); end; Ich denke ich mache da irgendwas total falsch. Ich mach mal eine Liste von Fragen, mit den Antworten komme ich bestimmt schon weiter. - Ist es normal, dass der Winsock.Send immer sofort zurückkommt? - Wenn ja, wie löse ich das Problem, dass nach kurzer Zeit der Speicher voll ist? - Was heisst Blocking/Non-Blocking? - Muss die TCP-Server/Client Verbindung als Thread laufen? Im Server und/oder im Client? - Muss ich einen Stream von 1MB, den ich verschicken will, selbst zerlegen, oder kann ich ihn direkt senden? - Kommen die Pakete in der richtigen Reihenfolge auf dem Server an, oder muss ich dafür auch was tun? - Wie unterscheide ich die einzelnen Clients? mfg Oliver |
Re: Daten per TCP/IP übertragen
1) Wenn Du schon die Indys zum Empfangen verwendest, warum nicht auch zum Senden?
2) Dann dürfte sich alles andere von selbst erledigen ;) Sherlock |
Re: Daten per TCP/IP übertragen
Zitat:
Hab ich ja im Client Bereich auch schon ein wenig geschafft. |
Re: Daten per TCP/IP übertragen
Ich sehe nicht ein, das Rad immer wieder neu erfinden zu müssen! Vor allem die Komponenten sind das, was Delphi angenehm von der grauen Masse unterscheidet. Die
![]() Natürlich werden die NonVCL Puristen aufschreien, aber denen kann ich nur ein gepflegtes "Warum habt Ihr dann Delphi gekauft?" entgegnen. ;) Viel Spaß! Sherlock |
Re: Daten per TCP/IP übertragen
Zitat:
|
Re: Daten per TCP/IP übertragen
Hast du dir mal die Beispeile zu ICS angesehen? Vorallem das TnSrv Bsp sollte doch passend sein
|
Re: Daten per TCP/IP übertragen
Zitat:
|
Re: Daten per TCP/IP übertragen
Mir fällt dazu noch das Stichwort Webservice an. Delphi hat iho doch dementsprechende Demos.
|
Re: Daten per TCP/IP übertragen
Liste der Anhänge anzeigen (Anzahl: 1)
Hmmmm, ich hab jetzt alles mal auf das Synapsis umgebaut, und wieder die gleichen Fehler bekommen.
Meine Vermutung war falsch, dass es am TCP lag. Das Problem ist ganz woanders. Es liegt am Thread. Vielleicht kann mir da einer weiter helfen. Das Szenario war bei allen TCP Sachen gleich. - Es läuft ein Hauptprogramm, was ein Log-Fenster pro Client führt - Es läuft ein TCP-Server im Thread - Pro Client wird ein Thread angelegt Wenn eine Verbindung in den TCP-Server reinkommt, erzeuge ich ein Client und lege ich ein neues Tabsheet auf meinem Hauptfenster an, an das ich den ClientThread übergebe. Ich denke, das Log-Fenster hängt dann oder meldet komische Fehler, weil der TCP-Server das Fenster erzeugt, und danach wieder in seinen "Ich warte auf Verbindungen" Modus geht. Der Client Thread macht ja auch das selbe, er wartet auf Daten. Nachdem ich mich in Thread-Handling ein bisschen eingearbeitet habe, habe ich Events gefunden. Diese soll man über Syncronize aufrufen können, damit nicht der TCP-Server, sondern der Hauptthread das Fenster öffnet. Leider klappt das ganze aber auch nicht. Er bleibt beim Aufruf des Sync Befehls stehen. Zusätzlich habe ich, weil der Sync ja nur einen Pointer übergeben bekommt, habe ich die Daten, die ich an den Hauptthread schicken will, mir im TCPServer Thread gemerkt (im Private Bereich), und dann in der Funktion wieder aufgerufen.
Delphi-Quellcode:
constructor TMainUnit.Create(aOwner: TComponent);
begin inherited; FTCPServer := TiBDITCPServer.Create; FTCPServer.OnClientAdded := CreateLogWindow; end;
Delphi-Quellcode:
procedure TiBDITCPServer.Execute;
var vClientSock: TSocket; vClient: TiBDITCPServerConnectionItem; begin FActive := True; FSocket.CreateSocket; FSocket.setLinger(true, 10); FSocket.bind('0.0.0.0', '4000'); FSocket.listen; repeat if terminated then break; if FSocket.canread(cDefaultCanReadTime) then begin if FSocket.lastError = 0 then begin vClientSock := FSocket.accept; vClient := TiBDITCPServerConnectionItem.Create(Self, vClientSock); FUpdateClient := vClient; Synchronize(SyncClientAdded); end; end; CheckConnections; until false; FActive := False; end;
Delphi-Quellcode:
Ich hab auch mal die Ganze TCPServer.pas mit angehangen.
procedure TiBDITCPServer.SyncClientAdded;
begin if Assigned(FOnClientAdded) then FOnClientAdded(Self, aClient); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:06 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 by Thomas Breitkreuz