Zitat von
WS1976:
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
Speicherzugriffsfehler, System out of resource. Wenn ich den Fehler beschreiben könnte, oder wüsste wo er her kommt, hätte ich das schon gemacht.
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:
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;
Die WinSock2.pas ist eine Umsetzung der Jedis aus dem Jahr 2000 von der Winsock.h.
Zum Senden des Pakets habe ich mir eine Funktion geschrieben:
Delphi-Quellcode:
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;
Empfangen tu ich das ganze mit den
Indy Tools via:
Delphi-Quellcode:
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;
Teilweise kommen System out of resource Meldungen, dann gehts wieder. Meistens hängt das Programm aber beim Execute.
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