Entwickler-Ecke

Internet / Netzwerk - Bitmap senden und empfangen - Wo ist der Fehler?


PhilippW - Sa 25.06.05 16:23
Titel: Bitmap senden und empfangen - Wo ist der Fehler?
Hallo!

Ich möchte gerne ein Bitmap mit Hilfe der Client/Server-Komponenten verschicken.
Das habe ich auch geschafft, allerdings nur von Client zum Server...
Nun hab ich es umgeschrieben, damit es das Bild vom Server zum Client schickt, aber irgendwie tritt immer eine Zugriffsverletzung auf... :(

Ich habe folgende zwei Programme geschrieben:

Server:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
...

procedure TForm1.FormCreate(Sender: TObject);
begin
  form1.ServerSocket1.Open;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  form1.ServerSocket1.Close;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  i: integer;
  Stream: TMemoryStream;
begin
  Stream:=TMemoryStream.Create;
  form1.Image1.Picture.Bitmap.SaveToStream(Stream);
  try
    form1.ServerSocket1.Socket.Connections[0].SendBuf(Stream,sizeof(Stream));
  except
    Stream.Free;
  end;
end;


Client:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
...

procedure TForm1.FormCreate(Sender: TObject);
begin
 form1.ClientSocket1.Open;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  form1.ClientSocket1.Close;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  form1.ClientSocket1.Socket.SendText('Picture');
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  Stream: TMemoryStream;
begin
  Stream:=TMemoryStream.Create;
  Socket.ReceiveBuf(Stream,Socket.ReceiveLength);
  Stream.Seek(0,soFromBeginning);
  try
    form1.Image1.Picture.Bitmap.LoadFromStream(Stream);
  except
    Stream.Free;
  end;
end;


Ich kann mir beim besten Willen nicht erklären, wo der Fehler steckt und hoffe, dass ihr mir helfen könnt...

Mit freundlichen Grüßen

Philipp

Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt.


PhilippW - Sa 25.06.05 17:48

Ich muss noch hinzufügen, dass ich das Programm, welches vom Client zum Server schickt in eine einzige Anwendung gepackt hab (Client und Server in einem Programm).
Es schickt also das Bild durchs Netzwerk zu sich selbst zurück.
Dies funktioniert auch umgekehrt, also vom Server zum Client, aber sobald ich das ganze in getrennte Anwendungen pack, funktioniert es nicht mehr... :bawling:
Ich weiß immer noch nicht, wo der Fehler liegt...


Jan11 - Fr 21.04.06 18:52

das wäre extrem geil, wenn das mal jemand beantworten würde, denn ich hab im moment das geiche problem =)


Jan11 - Sa 22.04.06 09:56

kann das wirklich keiner beantworten?


huhn - Sa 22.04.06 12:25

Wenn du mal das komplette project packst und uploadest guck ichs mir an ;)
//edit: probiers mal anstatt except mit finally, ansonsten wird der stream nur freigegeben wenn ein fehler auftritt!


Born-to-Frag - Sa 22.04.06 12:37

Wird wohl daran liegen, das das Bitmap nicht in einem Stück ankommt und du dafür schein ein kleines Protokoll schreiben musst indem du vorher die Größe des Bitmaps schickst und sobal die erreicht ist erst das image lädst.


greetz


huhn - Sa 22.04.06 13:17

habs hinbekommen ;)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ScktComp, ExtCtrls;

type
  TForm1 = class(TForm)
    CS: TClientSocket;
    SS: TServerSocket;
    Button1: TButton;
    Image1: TImage;
    OD: TOpenDialog;
    SCButton: TButton;
    Image2: TImage;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure SSClientRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure Button1Click(Sender: TObject);
    procedure SCButtonClick(Sender: TObject);
    procedure CSRead(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  SS.Open;
  CS.Open;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  CS.Close;
  SS.Close
end;

procedure TForm1.SSClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  Stream: TMemoryStream;
begin
  Stream:=TMemoryStream.Create;
  Image1.Picture.Bitmap.SaveToStream(Stream);
  Stream.Position:=0;
  try
    Socket.SendBuf(Stream,sizeof(stream));
  finally
    //Stream.Free; darf nicht sein da sonst während des sendens ein fehler auftritt...
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if not OD.Execute then exit;
image1.Picture.Bitmap.LoadFromFile(OD.FileName);
end;

procedure TForm1.SCButtonClick(Sender: TObject);
begin
CS.Socket.SendText('Picture');
end;

procedure TForm1.CSRead(Sender: TObject; Socket: TCustomWinSocket);
var
  Stream: TMemoryStream;
begin
  Stream:=TMemoryStream.Create;
  Socket.ReceiveBuf(Stream,Socket.ReceiveLength);
  Stream.Seek(0,soFromBeginning);
  try
    Image2.Picture.Bitmap.LoadFromStream(Stream);
    image2.Width:= Image2.Picture.Bitmap.Width;
    image2.Height:= Image2.Picture.Bitmap.Height;
  finally
    Stream.Free;
  end;
end;

end.


Born-to-Frag - Sa 22.04.06 13:26

Wird nicht mehr funktionieren wenn du die Programme aufteilst und wirklich etwas über das Internet senden wirst, oder sehe ich das falsch :?:

greetz


huhn - Sa 22.04.06 13:32

müsste man ausprobieren^^
//edit:born-to-frag hab dir ne pn geschickt


Narses - Mo 24.04.06 00:07

Moin!

Naja, bevor das noch jemand als "Vorlage" betrachtet... ;)

user profile iconhuhn hat folgendes geschrieben:
habs hinbekommen ;)

Nein, nur scheinbar (das wird nur mit Bildern <8kb und auf der gleichen Maschine einigermaßen brauchbar funktionieren). Der entscheidende Fehler ist hier:

Delphi-Quelltext
1:
Socket.ReceiveBuf(Stream,Socket.ReceiveLength);                    

Die DOH sagt dazu:
Delphi Online Hilfe hat folgendes geschrieben:
Use ReceiveBuf to read from the socket connection in the OnSocketEvent event handler of a Windows socket object or in the OnRead or OnClientRead event handler of a socket component. ReceiveBuf returns the number of bytes actually read. If no bytes are read, ReceiveBuf returns –1.

Du wertest nicht aus, wieviele Bytes tatsächlich gelesen wurden und reagierst demzufolge nicht darauf :arrow: das ist ein klarer Programmierfehler. Du stellst nicht sicher, dass alle Bytes gelesen werden. :shock: Noch viel schlimmer: Du verläßt dich darauf, dass dir .ReceiveLength die Größe des Streams liefert, und das ist leider wieder falsch. :|

Weiterhin verwendest du kein Protokoll, um eine Struktur in deine Datenübertragung zu bekommen; das ist zwar nicht unbedingt gleich als "falsch" anzusehen, aber sicherlich reichlich "unklug". Hier ist ein Tutorial [http://www.delphi-library.de/topic_ProtokollChatTutorial+TServerClientSocket++V201_54269.html], wie du ein Protokoll entwickeln und umsetzen kannst.

cu
Narses