Autor Beitrag
Shion
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Di 16.12.08 14:52 
bin dabei mir einen kleinen threat(unter Delphi 5) zu schrieben der aus mehreren stellen des hauptprogramms strings an den server senden soll.
da es teilweise auch vorkommen kann, dass das hauptrogramm versucht mehrere strings gleichzeitig zu senden hab ich das problem mit einer liste versucht abzufangen, wo ich mit dem OnWrite ereignis des clientsocket den gesendeten string aus der liste entfernen wolte.
Jedoch wird OnWrite nie ausgelöst und ich find leider auch keinen fehler hoffe es kann mir jemand helfen.
hier die interessenten code schnippsel dafür:

ausblenden volle Höhe 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:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
TClientLeitrechner = class(TThread)
private
  ftoSend:TStringlist;
  procedure OnConnect(Sender: TObject;Socket: TCustomWinSocket);
  procedure OnDisconnect(Sender: TObject;Socket: TCustomWinSocket);
  procedure OnRead(Sender: TObject; Socket: TCustomWinSocket);
  procedure OnWrite(Sender: TObject; Socket: TCustomWinSocket);
  procedure OnError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
protected
    procedure Execute; override;



constructor TClientLeitrechner.Create(path :string);
begin
  inherited create(True);
  try
    ...
    fkKontrolle := false;
    fFertig := false;
    fProgrammAblauf:=False;
    fconnect:=false;
    ftoSend:= TStringlist.Create;
    ClientSocket1 := TClientSocket.Create(nil) ;
    ClientSocket1.OnRead:= OnRead;
    ClientSocket1.OnWrite := OnWrite;
    ClientSocket1.OnConnect := OnConnect;
    ClientSocket1.OnDisconnect := OnDisconnect;
    ClientSocket1.OnError := OnError;
  except end;
  //FreeOnTerminate:=false;
  resume;
end;

destructor TClientLeitrechner.Close;
begin
  try
    ftoSend.Clear;
    fToSend.Destroy;
    ClientSocket1.Close;
    ClientSocket1.Free;
    fkKontrolle := False;
    terminate;
    if suspended then resume;
    waitfor;
  except end;
end;

function TClientLeitrechner.Verfuegbar : Boolean;
begin
  Result:=not fkKontrolle and fFertig and suspended;
end;

function TClientLeitrechner.Connect : Boolean;
begin
  with ClientSocket1 do
  begin
    active := false;
    ClientType := ctNonBlocking;
    Host:= fIP;
    Port := fPort;
    active := true;
  end;
  result := true;
end;

procedure TClientLeitrechner.OnConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  fConnect := true;
end;

procedure TClientLeitrechner.OnDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  fConnect := false;
end;

procedure TClientLeitrechner.OnError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  try
    case ErrorEvent of
      eeGeneral: fFatalError:='Der Socket erhielt eine Fehlermeldung, die in keine der folgenden Kategorien paßt';
      eeSend:    fFatalError:='Es trat ein Fehler bei dem Versuch auf, in die Socket-Verbindung zu schreiben';
      eeReceive: fFatalError:='Es trat ein Fehler bei dem Versuch auf, aus der Socket-Verbindung zu lesen';
      eeConnect: fFatalError:='Es konnte keine Verbindung zum Leitrechner hergestellt werden';
      eeDisconnect:fFatalError:='Es trat ein Fehler bei dem Versuch auf, eine Verbindung zu schließen';
      eeAccept:  fFatalError:='Es trat ein Fehler bei dem Versuch auf, eine Client-Verbindungsanforderung anzunehmen';
    end;
    fconnect := false;
    if(ClientSocket1.Active) then
      ClientSocket1.Close;
    ErrorCode:=0;
  except end;
end;

procedure TClientLeitrechner.OnWrite(Sender: TObject; Socket: TCustomWinSocket);
begin
  if ftoSend.Count>0 then
    ftoSend.Delete(0);
  if Verfuegbar then
  begin
    fProgrammAblauf:=false;
    fkKontrolle := True;
    resume;
  end;
end;

procedure TClientLeitrechner.OnRead(Sender: TObject; Socket: TCustomWinSocket);
begin
  fReceiveXML:= Clientsocket1.Socket.ReceiveText;
end;

function TClientLeitrechner.Send(value:string):boolean;
var cxml:boolean;
begin
  result := false;
  if Verfuegbar then
  begin
      fToSend.Add(value);  
      if not fconnect then Connect;
      if fconnect then
      begin
        fProgrammAblauf:=false;
        fkKontrolle := True;
        result := true;
        resume;
        result := true;
      end;
    end
    else begin
      result := false;
    end;
  end;
end;

function TClientLeitrechner.Senden(value:string) :Boolean;
var
  len: string;
 
begin
  result := false;
  if not fconnect then Connect;
  if  fconnect then
    if (fFatalError = '')then
      with ClientSocket1 do
      begin
        len := Char(Byte((length(value)+4)shr 24))+
            Char(Byte((length(value)+4)shr 16))+
            Char(Byte((length(value)+4)shr 8))+
            Char(Byte((length(value)+4)));
            Socket.SendText(len+value);
        result := true;
      end;
end;

procedure TClientLeitrechner.Execute;
begin
  try
    while not terminated do
    begin
      fFertig := True;
      suspend;
      fFertig := False;
      if not terminated then
      begin
        fProgrammAblauf:=true;
        if ftosend.Count >0 then
          Senden(ftosend.Strings[0]);
        fProgrammAblauf:=false;
        fkKontrolle := False;
        sleep(100);
      end;
    end;
  except end;
  // das Letzte
end;

hoffe es ist nicht zu unübersichtlich.
Geht auch aber nur immer für die erste Nachricht da das OnWrite nie ausgelöst wird um den ersten string in ftoSend zu löschen und den nächsten string zu senden.
Hoffe jemand findet den fehler.... danke schon mal fürs bis hierher durchlesen :lol:
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 16.12.08 17:53 
Moin und :welcome: im Forum!

user profile iconShion hat folgendes geschrieben Zum zitierten Posting springen:
wo ich mit dem OnWrite ereignis des clientsocket den gesendeten string aus der liste entfernen wolte.
Jedoch wird OnWrite nie ausgelöst und ich find leider auch keinen fehler hoffe es kann mir jemand helfen.
[...]
Geht auch aber nur immer für die erste Nachricht da das OnWrite nie ausgelöst wird um den ersten string in ftoSend zu löschen und den nächsten string zu senden.
Das ist ein Bug oder Design des TClientSocket, ganz nach Belieben. ;) Es wird nur direkt nach dem Connect ein OnWrite-Ereignis ausgelöst, danach nie wieder.

Wenn du aber doch keine Probleme mit Threads hast (wie´s aussieht), dann kannst du doch mit blocking-socket-calls arbeiten, dann brauchst du keine Ereignisse. :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Shion Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Di 16.12.08 20:06 
Hi Narses
danke für die antwort
hatte vorher mit ctBloking gearbeitet nur da der Leitrechnerserver auch auf bestimmte ereignise (Leider nicht immer in der Richtigen Reihenfolge wie die anfragen sind) antwortet macht sich das mit dem OnRead sehr gut was es ja bei ctBloking nicht gibt, drum hab ich gehoft, dass ich das irgendwie verwenden kann.
Aber wenn es ein bug mit OnWrite gibt werd ich Wohl alles wieder umstriken und mir mal nen kopf machen müssen wie ich die ankommenden strings richtig abfange :roll: