Autor Beitrag
winx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 249



BeitragVerfasst: Mi 07.06.06 09:55 
Guten Morgen,

ich hab mir einen kleinen Server aufgesetzt, der asynchron Daten von Clients empfangen kann.
Nur hab ich jetzt zwei Probleme:

1. Wie kann ich den einmal gestarteten Server wieder stoppen??? bekomm bei meinem
versuch (ButtonStopClick) immer die eine InvalidOperationException "AcceptCallback"

2. Wie bekommt mein Server mit, wenn sich ein angemeldeter Client mit ClientSocket.Shutdown(SocketShutdown.Both);
abmeldet??

Der Code meines Servers sieht so aus:

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:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
unit ServerMainFormManager;

interface

uses
 ...


type

  TServerMainFormManager = class
  private
    m_mainForm : TServerMainForm;
    m_socketListen : Socket;
    m_socketAccept : Socket;
    m_Backlog      : integer;
    m_WorkerCallback : AsyncCallback;
    Logger : ILog;
    m_CommandCompleteEvent : TCommandCompleteEventHandler;
    m_currentCommandString : string;
    m_currentCommandStringLocked : boolean;
    m_SendCommandAnswer : string;

    procedure acceptCallback(asyncResult : IAsyncResult);
    procedure onDataReceived(asyncResult : IAsyncResult);
    procedure waitForData(pSocket : Socket);
    procedure processData(newChar : string);

    //Events vom Formular
    procedure ButtonStartClicked(Sender: TObject; Args: EventArgs);
    procedure ButtonSendClicked(Sender: TObject; Args: EventArgs);
    procedure ButtonStopClicked(Sender: TObject; Args: EventArgs);

    //Events
    procedure removeCommandCompleteEvent(event : TCommandCompleteEventHandler);
    procedure addCommandCompleteEvent(event : TCommandCompleteEventHandler);

    function getCurrentCommandString: string;

  public

    property ReceivedCommandString : string read getCurrentCommandString;
    property CommandCompleteEventHandler : TCommandCompleteEventHandler add addCommandCompleteEvent remove removeCommandCompleteEvent;

    constructor Create;
    procedure start();
    procedure SendCommandAnswer(answer:string);

  end;

implementation


{$REGION 'Constructor'}
constructor TServerMainFormManager.Create;
begin
  inherited Create;
  Logger := LogManager.GetLogger('TServerMainFormManager');
  XmlConfigurator.Configure(FileInfo.Create('LogConfig.xml'));
  m_mainForm := TServerMainForm.Create();
  Include(m_mainForm.ButtonStart.Click,ButtonStartClicked);
  Include(m_mainForm.ButtonSend.Click,ButtonSendClicked);
  Include(m_mainForm.ButtonStopServer.Click,ButtonStopClicked);
  m_Backlog := 1;
end;



function TServerMainFormManager.getCurrentCommandString: string;
begin

  //Zuerst den String Locken
  Result := m_currentCommandString;

end;

{$ENDREGION}



{$REGION 'Mainform Events'}
procedure TServerMainFormManager.ButtonStartClicked(Sender: TObject;Args: EventArgs);
var serverPort : integer;
begin

  try

    //einen neuen socket erzeugen
    m_socketListen := Socket.Create(AddressFamily.InterNetwork,
                                    SocketType.Stream,
                                    ProtocolType.Tcp);

    Logger.Debug('New Socket created, Port: '+m_mainForm.NumericUpDownPort.Value.ToString());

    //Port auslesen
    serverPort := Convert.ToInt32(m_mainForm.NumericUpDownPort.Value);
    m_socketListen.Bind(IPEndPoint.Create(IPAddress.Any,serverPort));
    Logger.Debug('Socket Bind');


    //Das Listening starten
    m_socketListen.Listen(m_Backlog);
    Logger.Debug('Socket listening');

    //Rückruf für jeden Clienten
    m_socketListen.BeginAccept(acceptCallback,nil);
    Logger.Debug('Socket waits for Clients');

    if (m_socketListen.Connected) then
      Logger.Debug('Connected');

    m_mainForm.ButtonStart.Enabled := false;
    m_mainForm.ButtonStoPServer.Enabled := true;
    m_mainForm.NumericUpDownPort.Enabled := false;

  except
    on E:SocketException do begin
       Logger.Error(E.Message);
    end;
  end;


end;



procedure TServerMainFormManager.ButtonStopClicked(Sender: TObject;
  Args: EventArgs);
begin

   try

    if assigned(m_socketAccept) and (m_socketAccept.Connected) then
      m_socketAccept.Shutdown(SocketShutdown.Both);

    if assigned(m_socketListen) and m_socketListen.Connected then begin

      m_socketListen.Shutdown(SocketShutdown.Both);
    end;


    m_socketListen.Close();

    m_mainForm.ButtonStart.Enabled := true;
    m_mainForm.ButtonStoPServer.Enabled := false;
    m_mainForm.NumericUpDownPort.Enabled := true;


  except
    on E:SocketException do begin
       Logger.Error(E.Message);
    end;
  end;
end;



procedure TServerMainFormManager.ButtonSendClicked(Sender: TObject;Args: EventArgs);
var objData : TObject;
    byteData : array of byte;
begin

  try

    //Sende Daten an den Client
    Logger.Debug('Send Data to Client...');
    objData := m_mainForm.TextBoxSend.Text;
    byteData := System.Text.Encoding.ASCII.GetBytes(objData.ToString());
    m_socketAccept.Send(byteData);
    Logger.Debug('Data send to Client successful');

  except
    on E:Exception  do
      Logger.Error(E.Message);
  end;


end;





{$ENDREGION}



{$REGION 'Private Functions'}
procedure TServerMainFormManager.removeCommandCompleteEvent(event: TCommandCompleteEventHandler);
begin
  m_CommandCompleteEvent := TCommandCompleteEventHandler(Delegate.Remove(@m_CommandCompleteEvent,@event));
end;



procedure TServerMainFormManager.addCommandCompleteEvent(event : TCommandCompleteEventHandler);
begin
  m_CommandCompleteEvent := TCommandCompleteEventHandler(Delegate.Combine(@m_CommandCompleteEvent,@event));
end;

{$ENDREGION}



procedure TServerMainFormManager.start;
begin
  m_mainForm.ShowDialog();
end;



procedure TServerMainFormManager.acceptCallback(asyncResult: IAsyncResult);
begin

  try

      //Callback
      Logger.Debug('Callback');
      m_socketAccept := m_socketListen.EndAccept(asyncResult);
      waitForData(m_socketAccept);

  except
    on E:SocketException do
      Logger.Error(E.Message);
  end;

end;



procedure TServerMainFormManager.waitForData(pSocket: Socket);
var socPkt : TSocketPacket;
begin

  try

    if not assigned(m_WorkerCallback) then begin
      m_WorkerCallback := ondataReceived;
    end;


     socPkt := TSocketPacket.Create();
     socPkt.socket := pSocket;

     //now start to listen for data
     Logger.Debug('Listening for any data...');
     pSocket.BeginReceive(socPkt.dataBuffer,
                           0,
                           length(socPkt.databuffer),
                           SocketFlags.None,
                           m_WorkerCallback,
                           socPkt);

  except
    on E:Exception  do
      Logger.Error(E.Message);
  end;

end;



procedure TServerMainFormManager.onDataReceived(asyncResult: IAsyncResult);
var theSockID : TSocketPacket;
    iRx, charLen : integer;
    dec : Decoder;
    chars : array of char;
    szData : string;
begin

  try

    theSockID := TSocketPacket(asyncResult.AsyncState);

    
    //Empfange die Daten
    Logger.Debug('Receive Data');

    iRx   := theSockID.socket.EndReceive(asyncResult);
    SetLength(chars,iRx+1);
    dec := System.Text.Encoding.ASCII.GetDecoder();

    charLen := dec.GetChars(theSockID.dataBuffer, 0, iRx, chars, 0);

    szData := string(chars);
    m_mainForm.TextBoxReceived.Text := m_mainForm.TextBoxReceived.Text + szData;

    //Die Daten werden verarbeitet
    processData(szData);

    Logger.Debug(m_currentCommandString);
    waitForData(m_socketAccept);

  except
    on E:ObjectDisposedException  do
      Logger.Debug('OnDataReceived: Socket has been closed');
    on E: SocketException do
      Logger.Error(E.Message);
  end;

end;



procedure TServerMainFormManager.processData(newChar: string);
begin
  ...
end;



procedure TServerMainFormManager.SendCommandAnswer(answer: string);
begin
  ...
end;

end.


danke,
winx

ps: hab das thema auch hier gepostet:
www.delphipraxis.net...st559848.html#559848


Moderiert von user profile iconChristian S.: Topic aus .NET verschoben am Mi 07.06.2006 um 12:56