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



BeitragVerfasst: Mo 10.12.07 12:09 
Hi,

ich habe einen Server der per TCP/IP mit Clients kommuniziert. Daten anmelden,senden & empfangen funktioniert einwandfrei.
Mein Problem ist nun das der Server anscheinend selbstständig die Verbindung zum Client trennt... wie kann sowas vorkommen,
bzw welche Einstellungen am Socket muß ich treffen, damit sowas nicht mehr passiert?

ausblenden volle Höhe C#-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:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
413:
414:
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426:
427:
428:
429:
430:
431:
432:
433:
434:
435:
436:
437:
438:
439:
440:
441:
442:
443:
444:
445:
446:
447:
448:
449:
450:
451:
452:
453:
454:
455:
456:
457:
458:
459:
460:
461:
462:
463:
464:
465:
466:
467:
468:
469:
470:
471:
472:
473:
474:
475:
476:
477:
478:
479:
480:
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
using Server.GUI;
using Remoting;
using log4net;




namespace Server.TcpIP
{

    /// <summary>
    /// Delegat für das Setzen von Texten im Formular
    /// </summary>
    /// <param name="text">Der zu setzende Text</param>
    delegate void SetReceivedText(string text);

    delegate void AddProcessState(string text);
    delegate void ClearProcessStates();
    delegate void StartListening();



    internal class TCPIPServer
    {

        #region private Members
        
        /// <summary>
        /// Der Logger der Klasse
        /// </summary>
        private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        private CommandRemoting m_CommandRemotingObject;


        /// <summary>
        /// Das Formular, auf dem die Daten angezeigt und auf dem geloggt wird
        /// </summary>
        private SocketServerForm m_ServerForm;

        public SocketServerForm ServerForm
        {
            get { return m_ServerForm; }
        }
        

        /// <summary>
        /// Ein Asynchrone Funktion, die aufgerufen wird, sobald...
        /// </summary>
        //public AsyncCallback pfnWorkerCallBack;


        


        /// <summary>
        /// Der Hauptsocket des Servers, an diesem werden Listener 
        /// Anfragen angenommen
        /// </summary>
        private Socket m_ListenForClientsSocket;
        


        /// <summary>
        /// Die Anzahl der aktuell aktiven Clients
        /// </summary>
        private int m_clientCount = 0;


        /// <summary>
        /// Die maximal erlaubte Anzahl an Clients, die sich
        /// anmelden dürfen
        /// </summary>
        const int MAX_CLIENTS = 100;


        /// <summary>
        /// Handelt alle Clients (Eigentlich "WorkerSockets"), speichert diese in einer Liste und 
        /// schickt Nachrichten an den Client
        /// Eine Liste mit allen Worker Sockets (pro neuem Client ein Socket)
        /// dieser Socket nimmt alle Nachrichten von Clients entgegen und sendet diese auch
        /// </summary>
        private ClientManager m_ClientManager;

        #endregion


        #region Constructor and Singleton Instance Function

        internal TCPIPServer(CommandRemoting crObject)
        {
            m_CommandRemotingObject = crObject;
            init();
        }


        /// <summary>
        /// Standardkonstruktor der Klasse
        /// </summary>
        internal TCPIPServer()
        {
            init();            
        }               
             

        

        #endregion



        #region private Functions

        private void init()
        {
            m_ClientManager = new ClientManager();
            m_ServerForm = new SocketServerForm();
            // Die lokale IP in die GUI schreiben
            m_ServerForm.textBoxIP.Text = Properties.Settings.Default.HostIP;
            m_ServerForm.textBoxPort.Text = Properties.Settings.Default.ServerListenerPort.ToString();

            m_CommandRemotingObject.setServerAndPort(Properties.Settings.Default.HostIP, Properties.Settings.Default.ServerListenerPort.ToString());

            //Alle Events des Forms registrieren
            m_ServerForm.buttonClose.Click += new EventHandler(buttonClose_Click);
            m_ServerForm.buttonStartListen.Click += new EventHandler(buttonStartListen_Click);
            m_ServerForm.buttonStopListen.Click += new EventHandler(buttonStopListen_Click);
            m_ServerForm.buttonSendMsg.Click += new EventHandler(buttonSendMsg_Click);
            m_CommandRemotingObject.StartServerEvent += new StartServer(m_CommandRemotingObject_StartServerEvent);
            m_CommandRemotingObject.StopServerEvent += new StopServer(m_CommandRemotingObject_StopServerEvent);
        }



        void m_CommandRemotingObject_StopServerEvent()
        {
            this.CloseSockets();
        }



        void m_CommandRemotingObject_StartServerEvent()
        {
            this.startListening();
        }


        #region private event Functions (Events vom Formular)
        
    
        /// <summary>
        /// Der Start Listening Knopf wird gedrückt und der
        /// Server geht in den "Warte-auf-Clients" Modus über
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonStartListen_Click(object sender, EventArgs e)
        {
            //this.startListening();
        }



        /// <summary>
        /// Server geht in den "Warte-auf-Clients" Modus über
        /// </summary>
        public void startListening()
        {
            if (m_ServerForm.InvokeRequired)
            {
                m_ServerForm.Invoke(new StartListening(startListening));
                return;
            }


            try
            {
                // Check the port value
                if (m_ServerForm.textBoxPort.Text == "")
                {
                    MessageBox.Show("Please enter a Port Number");
                    return;
                }
                string portStr = m_ServerForm.textBoxPort.Text;
                int port = System.Convert.ToInt32(portStr);
                // Create the listening socket...
                m_ListenForClientsSocket = new Socket(AddressFamily.InterNetwork,
                                          SocketType.Stream,
                                          ProtocolType.Tcp);
                // IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port);
                IPAddress hostIPAddress = IPAddress.Parse(Properties.Settings.Default.HostIP);
                IPEndPoint ipLocal = new IPEndPoint(hostIPAddress, port);
                // Bind to local IP Address...
                m_ListenForClientsSocket.Bind(ipLocal);
                // Start listening...
                m_ListenForClientsSocket.Listen(4);
                // Create the call back for any client connections...
                m_ListenForClientsSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);

                UpdateControls(true);


            }
            catch (SocketException se)
            {
                Logger.Error(se.Message);
            }
 
        }

        
        /// <summary>
        /// Eine Broadcast Nachricht an alle Clients schicken
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void buttonSendMsg_Click(object sender, EventArgs e)
        {
            try
            {
                Object objData = m_ServerForm.richTextBoxSendMsg.Text;
                byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
                foreach (Client client in m_ClientManager.Clients)
                {

                    if ((client != null) && (client.ClientSocket != null))
                    {                        

                        if (client.ClientSocket.Connected)
                        {
                            client.ClientSocket.Send(byData);
                        }
 
                    }

                }
                

            }
            catch (SocketException se)
            {
                Logger.Error(se.Message);
            }
        }


        
        /// <summary>
        /// Knopf Stop Listening wurde gedrückt
        /// Das Listening stoppen
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void buttonStopListen_Click(object sender, EventArgs e)
        {
            CloseSockets();
            UpdateControls(false);
        }


        /// <summary>
        /// Der Applikation schließen Knopf wurde betätigt,
        /// alle Sockets geschlossen und das Form geschlossen
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>    
        private void buttonClose_Click(object sender, EventArgs e)
        {
            CloseSockets();
            m_ServerForm.Close();
        }




        #endregion


        /// <summary>
        /// Switched die beiden Knöpfe um, je nachdme ob der Server 
        /// läuft oder nicht
        /// </summary>
        /// <param name="listening">Gibt an ob der Server läuft</param>
        public void UpdateControls(bool listening)
        {
            m_ServerForm.buttonStartListen.Enabled = !listening;
            m_ServerForm.buttonStopListen.Enabled = listening;
        }



        /// <summary>
        /// Diese Callback Funktion wird aufgerufen, wenn ein Client verbunden
        /// ist        
        /// "This is the call back function, which will be invoked when a client is connected"
        /// </summary>
        /// <param name="asyn"></param>
        private void OnClientConnect(IAsyncResult asyn)
        {
            try
            {
                // Here we complete/end the BeginAccept() asynchronous call
                // by calling EndAccept() - which returns the reference to
                // a new Socket object
                Socket newSocket = m_ListenForClientsSocket.EndAccept(asyn);

                Logger.Debug("New Client Connection (IP: " + newSocket.RemoteEndPoint.ToString() + ", Port: " + ((IPEndPoint)newSocket.LocalEndPoint).Port.ToString() + ")");
                m_CommandRemotingObject.newClientConnected(newSocket.RemoteEndPoint.ToString());
                Client newClient = new Client(newSocket);

                m_ClientManager.Clients.Add(newClient);                

                // Let the worker Socket do the further processing for the 
                // just connected client
                newClient.WaitForData();
                // Now increment the client count
                ++m_clientCount;
                // Display this client connection as a status message on the GUI  
                String str = String.Format("Client # {0} connected", m_clientCount);

                setTextBoxMsgText(str);

                // Since the main Socket is now free, it can go back and wait for
                // other clients who are attempting to connect
                m_ListenForClientsSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
            }
            catch (ObjectDisposedException)
            {
                System.Diagnostics.Debugger.Log(0"1""\n OnClientConnection: Socket has been closed\n");
            }
            catch (SocketException se)
            {
                Logger.Error(se.Message);
            }

        }


       

        /// <summary>
        /// Ermittelt die lokale IP
        /// </summary>
        /// <returns>IP des Servers</returns>
        private String GetIP()
        {
            String strHostName = Dns.GetHostName();

            // Find host by name
            IPHostEntry iphostentry = Dns.GetHostEntry(strHostName);

            // Grab the first IP addresses
            String IPStr = "";
            foreach (IPAddress ipaddress in iphostentry.AddressList)
            {
                IPStr = ipaddress.ToString();
                return IPStr;
            }
            return IPStr;
        }




        /// <summary>
        /// Schließt alle Sockets
        /// </summary>
        private void CloseSockets()
        {
            if (m_ListenForClientsSocket != null)
            {
                m_ListenForClientsSocket.Close();
            }

            while (m_ClientManager.Clients.Count > 0)
            {
                if (m_ClientManager.Clients[0] != null)
                { 
                    m_ClientManager.Clients[0].ClientSocket.Close();
                    m_ClientManager.Clients.Remove(m_ClientManager.Clients[0]);
                }
            }                    
           
        }


        #region Invoke Funktionen zum Zugriff auf Formularkomponenten

        /// <summary>
        /// Fügt Text in die Box des Formulars ein
        /// </summary>
        /// <param name="text">Der anzufuegende Text</param>
        private void appendTextToReceivedTextBoxSPS(string text)
        {
            if (m_ServerForm.richTextBoxReceivedMsgFromSPS.InvokeRequired)
            {
                m_ServerForm.richTextBoxReceivedMsgFromSPS.Invoke(new SetReceivedText(appendTextToReceivedTextBoxSPS), new object[] { text });
                return;
            }

            m_ServerForm.richTextBoxReceivedMsgFromSPS.AppendText(text);

        }

        
        /// <summary>
        /// Fügt Text in die Box des Formulars ein
        /// </summary>
        /// <param name="text">Der anzufuegende Text</param>
        public void appendTextToReadyWTBox(string szData)
        {
            if (m_ServerForm.richTextBoxReadyWTs.InvokeRequired)
            {
                m_ServerForm.richTextBoxReadyWTs.Invoke(new SetReceivedText(appendTextToReadyWTBox), new object[] { szData });                    
                return;
            }

            m_ServerForm.richTextBoxReadyWTs.AppendText(szData+"\r\n");
        }




        /// <summary>
        /// Fügt Text in die TextBox des Formulars ein
        /// </summary>
        /// <param name="text">Der anzufuegende Text</param>
        private void setTextBoxMsgText(string text)
        {
            if (m_ServerForm.textBoxMsg.InvokeRequired)
            {
                //setReceivedText del = new setReceivedText(setTextBoxMsgText);
                m_ServerForm.textBoxMsg.Invoke(new SetReceivedText(setTextBoxMsgText), new object[] { text });
                return;
            }

            m_ServerForm.textBoxMsg.Text = text;

        }
        #endregion




        #endregion



        #region public Functions


        public void showForm()
        {
            if (m_ServerForm != null)
            {
                m_ServerForm.Show();
            }
        }



        public void addProcessState(string state)
        {
            if (m_ServerForm.InvokeRequired)
            {
                m_ServerForm.Invoke(new AddProcessState(addProcessState), new Object[] { state });
                return;
            }

            m_ServerForm.richTextBoxProcessState.Text = m_ServerForm.richTextBoxProcessState.Text + "\r\n" + state;
        }


        public void clearProcessStates()
        {
            if (m_ServerForm.InvokeRequired)
            {
                m_ServerForm.Invoke(new ClearProcessStates(clearProcessStates));
                return;
            }

            m_ServerForm.richTextBoxProcessState.Text = String.Empty; 


        }

       #endregion
  }
}


Jeder "Client" wird dabei in einer eigenen Klasse verwaltet, die das Senden & Empfangen managed:

ausblenden volle Höhe C#-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:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
413:
414:
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426:
427:
428:
429:
430:
431:
432:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using Server.Commands;
using Server.Utility;

namespace Server.TcpIP
{

    /// <summary>
    /// Repräsentiert den Client auf der Windows Seite
    /// Nach dem Verbinden wird immer ein  neuer Client angelegt
    /// 
    /// </summary>
    internal class Client
    {

        #region private Members

        /// <summary>
        /// Der socket, der mit dem "eigentlichen Client" verbunden ist
        /// </summary>
        private Socket m_ClientSocket;
        private AsyncCallback m_AsyncCallbackFunction;
        private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        //Die IP des Clients, dient zur eindeutigen Identifizierung, ob SPS oder XLS
        private string m_IP;
        private string m_receivedData = String.Empty;


        #endregion



        #region Properties


        public Socket ClientSocket
        {
            get { return m_ClientSocket; }
            set { m_ClientSocket = value; }
        }



        public AsyncCallback AsyncCallbackFunction
        {
            get { return m_AsyncCallbackFunction; }
            set { m_AsyncCallbackFunction = value; }
        }



        public string IP
        {
            get { return m_IP; }
        }


        #endregion



        #region Constructor and Singleton Instance Function

        internal Client(Socket sock)
        {
            m_ClientSocket = sock;
            m_IP = sock.RemoteEndPoint.ToString();
            Processing.ProcessHandler.Instance.DistanceReadReadyEvent += new Server.Processing.DistanceReadReady(Instance_DistanceReadReadyEvent);
            Processing.ProcessHandler.Instance.CamReadyEvent += new Server.Processing.CamReady(Instance_CamReadyEvent);
            Processing.ProcessHandler.Instance.MarkingReadyEvent += new Server.Processing.MarkingReady(Instance_MarkingReadyEvent);
            Processing.ProcessHandler.Instance.ErrorOccuredEvent += new Server.Processing.ErrorOccured(Instance_ErrorOccuredEvent);
            Processing.ProcessHandler.Instance.SwitchOnLightEvent += new Server.Processing.SwitchOnLight(Instance_SwitchOnLightEvent);
            CommandFactory.Instance.CommandErrorEvent += new CommandError(Instance_CommandErrorEvent);


        }



        /// <summary>
        /// Schaltet das Licht an :-)
        /// </summary>
        /// <param name="situation">1 = Barcode Fehler, 2 = Artikel nicht gefunden, 3 = EmptyWT, 4 = anderer Fehler</param>
        void Instance_SwitchOnLightEvent(int situation)
        {
            //this.sendData(Constants.SwitchLightOnCommand);            
        }


        #endregion



        #region private Functions


        /// <summary>
        /// Wartet auf Daten vom Client 
        /// "Start waiting for data from the client"
        /// Sobald Daten empfangen wurden, wird die Funktion OnDataReceveid aufgerufen
        /// </summary>
        /// <param name="soc">Der Socket von dem Daten empfangen werden sollen</param>
        public void WaitForData()
        {
            try
            {


                //Wenn es zwar den client schon gibt, jedoch noch keine
                //rückruffunktion existiert, diese belegen
                if (m_AsyncCallbackFunction == null)
                {
                    this.m_AsyncCallbackFunction = new AsyncCallback(OnDataReceived);
                }


                SocketPacket theSocPkt = new SocketPacket();
                theSocPkt.CurrentSocket = this.m_ClientSocket;


                // Start receiving any data written by the connected client
                // asynchronously
                this.m_ClientSocket.BeginReceive(theSocPkt.DataBuffer, 0,
                                       theSocPkt.DataBuffer.Length,
                                       SocketFlags.None,
                                       m_AsyncCallbackFunction,
                                       theSocPkt);




            }
            catch (SocketException se)
            {

                Logger.Error(se.Message);
            }

        }


        /// <summary>
        /// Diese Funktion empfängt die Daten von der SPS
        /// "This the call back function which will be invoked when the socket
        /// detects any client writing of data on the stream"        
        /// </summary>
        /// <param name="asyn"></param>
        private void OnDataReceived(IAsyncResult asyn)
        {
            try
            {
                SocketPacket socketData = (SocketPacket)asyn.AsyncState;

                int iRx = 0;
                // Complete the BeginReceive() asynchronous call by EndReceive() method
                // which will return the number of characters written to the stream 
                // by the client
                iRx = socketData.CurrentSocket.EndReceive(asyn);
                char[] chars = new char[iRx + 1];
                System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                int charLen = d.GetChars(socketData.DataBuffer,
                                         0, iRx, chars, 0);
                System.String szData = new System.String(chars);

                //Wenn das Startzeichen kommt ist, sprich
                //der String mit "(" begonnen wird, wird der String zurückgesetzt                
                if ((m_NewCommandStarted == false)&&(szData.Contains(Utility.Constants.cStartSign)))
                {
                    m_receivedData = Utility.Constants.cStartSign;
                    m_NewCommandStarted = true;
                } 
                else                                   
                    m_receivedData += szData[0];
                
                //Wenn nun das Schlußzeichen erreicht ist, sprich
                //der String mit ")" abgeschlossen wurde
                //wird das Ereignis gehandelt
                if ( (m_receivedData.EndsWith(Utility.Constants.cEndSign)) && (m_NewCommandStarted))
                {
                    m_NewCommandStarted = false;
                    StringBuilder builder = new StringBuilder(m_receivedData);
                    commandReceived(builder.ToString());
                    m_receivedData = String.Empty;

                }

                // Continue the waiting for data on the Socket
                //WaitForData(socketData.CurrentSocket);
                WaitForData();
            }
            catch (ObjectDisposedException)
            {
                System.Diagnostics.Debugger.Log(0"1""\nOnDataReceived: Socket has been closed\n");
            }
            catch (SocketException se)
            {
                Logger.Error(se.Message);
            }
        }


        /// <summary>
        /// Wird immer auf true gesetzt, sobald das Startzeichen empfangen wurde
        /// und auf false, wenn das Schlußzeichen empfangen wurde
        /// </summary>
        private bool m_NewCommandStarted = false;


        private void commandReceived(string receivedCommandString)
        {

            //Nachdem nun ein Kommando empfangen wurde, wird dies dem CommandManager übergeben

            Logger.Error("********************************************************");
            
            //Logger.Debug("Command received SPS  : [" + receivedCommandString+"]");
            //Logger.Debug("Commandlength: " + receivedCommandString.Length.ToString());
            string commandString = receivedCommandString.Replace("\0","");
            commandString = commandString.Replace(" """);

            Logger.Error("Command received'n'cut : [" + commandString + "]");
            //Logger.Debug("Command length: " + commandString.Length.ToString());

            Logger.Error("********************************************************");

            //Wenn es sich um das "Connected" Kommando handelt sofort zurück damit
            if (receivedCommandString.Equals(Constants.cConnectedCommandReceive))
            {
                this.sendData(Constants.cConnectedCommandAnswer);
                return;
            }

            //Wenn es sich um einen Lampen Befehl handelt, diesen verwerfen
            if (receivedCommandString.Equals(Constants.cLampCommandReceive))
            {                
                return;
            }



            CommandFactory.Instance.newCommandReceived(commandString, this.m_IP);

        }



        private void Instance_DistanceReadReadyEvent(Server.Processing.ProcessItem pi)
        {

            string answer = createStationAnswerCommand(pi, String.Empty);
            sendData(answer);
        }




        void Instance_MarkingReadyEvent(Server.Processing.ProcessItem pi)
        {
            string answer = createStationAnswerCommand(pi, String.Empty);
            sendData(answer);
        }



        void Instance_CamReadyEvent(Server.Processing.ProcessItem pi)
        {
            string answer = createStationAnswerCommand(pi, String.Empty);
            sendData(answer);
        }


        /// <summary>
        /// Ein Fehler ist aufgetreten, Rückmeldung an SPS
        /// </summary>
        /// <param name="pi">Das PI bei dem der Fehler aufgereten ist</param>
        void Instance_ErrorOccuredEvent(Server.Processing.ProcessItem pi, string station)
        {
            return// TO DO
            string answer = createStationAnswerCommand(pi, station);
            sendData(answer);

        }



        /// <summary>
        /// Wenn das Kommando ungültig war
        /// </summary>
        /// <param name="errorCode"></param>
        void Instance_CommandErrorEvent(int errorCode)
        {
            return;// TO DO
            string answer = Constants.cStartSign + "0" + Constants.cDelimiter +Constants.cError +Constants.cDelimiter + errorCode + Constants.cEndSign;
            sendData(answer);

        }



        /// <summary>
        /// Erzeugt eine Antwort
        /// </summary>
        /// <param name="pi">Das ProcessItem der Antwort</param>
        /// <param name="errorStation">Leerer Sting, falls kein Fehler, sonst die Station an der der Fehler passiert ist oder ERROR bei generellem Fehler</param>
        /// <returns>Die erzeugte Antwort</returns>
        private string createStationAnswerCommand(Server.Processing.ProcessItem pi, String errorStation)
        {
            //Jetzt das Antwort aus dem PI erzeugen Commando erzeugen
            string answer = Constants.cStartSign; //Startzeichen

            //Wenn das Pi nicht gefunden wurde und == null ist
            if (pi == null)
            {

                answer = answer + "0"//ID des WT WICHTIGSTE ZAHL, dient der Identifikation
                answer = answer + Constants.cDelimiter;//Trennzeichen
                answer = answer + errorStation;//Fehler
                answer = answer + Constants.cDelimiter;//Trennzeichen           
                answer = answer + "0";//Fehlercode, muß noch festgelegt werden 
            }
            else
            {

                answer = answer + pi.ID; //ID des WT WICHTIGSTE ZAHL, dient der Identifikation
                answer = answer + Constants.cDelimiter;//Trennzeichen

                //Leerer WT gefunden, Spezialmeldung raushauen
                if (pi.ProcessState.Equals(Processing.ProcessStates.EmptyWTDetected))
                {
                    

                    answer = answer + pi.StationCommand.Station;//Fehler
                    answer = answer + Constants.cDelimiter;//Trennzeichen           

                    //Wenn wir uns bei der Distance befinden dann die 1 senden, sonst die 0
                    if (pi.StationCommand.Station.Equals(Constants.cDistance))
                        answer = answer + Constants.cEmptyWT;//Code für EmtpyWT
                    else
                        answer = answer + "0";//Code für OK
                }
                //Jetzt muß unterschieden werden, ob ein Fehler aufgetreten ist
                else if (pi.ProcessState.Equals(Processing.ProcessStates.ErrorOccured))
                {
                    answer = answer + errorStation;//Fehler
                    answer = answer + Constants.cDelimiter;//Trennzeichen           
                    answer = answer + pi.ErrorCode.ToString();//Fehlercode, siehe Dokument Fehlercodes.doc                            

                }
                else //Kein Fehler
                {
                    answer = answer + pi.StationCommand.Station;//Die Station die es betrifft
                    answer = answer + Constants.cDelimiter;//Trennzeichen
                    answer = answer + "0";
                }


            }
            answer = answer + Constants.cEndSign; //Abschlußzeichen
            return answer;

        }


        


        private bool m_SendToSPSLock = false;

        /// <summary>
        /// Schickt einen String an den Client
        /// </summary>
        /// <param name="data">Der String der gesendet werden soll</param>
        private void sendData(string data)
        {
            try
            {
                //Zuerst das Lock abfragen
                while (m_SendToSPSLock)
                {
                    System.Threading.Thread.Sleep(200);
                }

                //Dann locken
                m_SendToSPSLock = true;

                Object objData = data;
                byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
                m_receivedData = String.Empty;
                try
                {
                    m_ClientSocket.Send(byData);
                    Logger.Info("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
                    Logger.Info("Data send to SPS: [" + data+"]");
                    Logger.Info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                }
                catch (Exception e)
                {
                    Logger.Error("Client disconnected: "+e.Message);
                }
            }
            finally
            {
                //und wieder freigeben
                m_SendToSPSLock = false;
            }



        }
        #endregion



        #region public Functions



        #endregion








    }
}



Danke für jeglich Tipps (auch wenn der Sourceode vielleicht gar nich nötig ist) !!!

gruß,
winx
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 10.12.07 14:13 
Kenne mich mit dem Zeugs nicht aus, aber wird deine Serverklasse möglicherweise einfach vom GC freigegeben? So oder so sollte sie wohl IDisposable implementieren, da das ihr Socket ebenfalls macht.
winx Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 249



BeitragVerfasst: Di 11.12.07 10:28 
Hi,

Ich poste hier mal Ausschnitte aus meinem Logfile.
sowohl beim Senden als auch beim Empfangen:

2007-12-07 13:17:32,296 [21] Client.sendData: Client disconnected: Eine vorhandene Verbindung wurde vom Remotehost geschlossen

2007-12-07 13:16:34,687 [3] Client.OnDataReceived: Eine vorhandene Verbindung wurde vom Remotehost geschlossen

Also irgendwie unregelmäßig und auch nicht nach langer Inaktivität:

Zum Beispiel hier:

2007-12-07 13:16:34,687 [3] Client.OnDataReceived: Eine vorhandene Verbindung wurde vom Remotehost geschlossen

2007-12-07 13:16:40,265 [3] TCPIPServer.OnClientConnect: New Client Connection (IP: 172.16.2.166:5, Port: 8000)

2007-12-07 13:16:40,296 [3] Client.commandReceived: Command received


wurde die Verbindung zuerst unterbrochen, dann hat sich der Client wieder vebunden und was erfolgreich gesendet.

kurze Zeit später hat er wieder was erflogreich empfangen, aber beim Senden dann der Fehler:


2007-12-07 13:17:23,609 [3] Client.commandReceived: Command received

2007-12-07 13:17:23,656 [24] Client.sendData: Client disconnected: Eine vorhandene Verbindung wurde vom Remotehost geschlossen


Also irgendwie ganz, ganz kurios... aber der GC kann doch nicht einfach so schnell was freigeben, oder???

Danke für weitere Tipps,
winx