c# Socket Problem



  • Hallo zusammen,

    ich hoffe Ihr könnt mir helfen.
    Also gut ich habe eine Client Server anwendung geschrieben in C#.
    Die ganze Socket Kommunikatino läuft Asynchron. Das Porblem tritt nun auf,
    wenn ich meine Socket Kommunikation Per Click auf einen Stop knopf beenden will und nach einem Click auf Start wieder aufnehmen möchte.
    Das ganze Problem sowie ich meine liegt am Socket.Shutdown befehl.
    Ich führe erst den Socket.Shutdown aus und dann mache ich Socket.Close.
    Wenn ich nun das Programm beende, läuft aber Trotzdem noch was.
    Wenn ich dann so ca. 5-10 sekunden warte ist das Programm aus.
    Ich denke mal das ist der Garbage collector der dann das geschlossene Socketobjekt aus dem Speicher schmeißt. Auserdem funktioniert der Socket.Shutdown nich, die Exception gibt immer folgende meldung aus:

    Eine Anforderung zum Senden oder Empfangen von Daten wurde verhindert, da der Socket nicht verbunden ist und (beim Senden über einen Datagrammsocket mit einem sendto-Aufruf) keine Adresse angegeben wurde

    Hier der SourceCode

    using System;
    using System.Threading;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    
    namespace SSIM2
    {
    	/// <summary>
    	/// Zusammenfassung für SocketCommunicationComponent.
    	/// Abgeleitet von AbstractCommunicationComponent
    	/// </summary>
    	[Serializable]
    	public class SocketCommunicationComponent : AbstractCommunicationComponent
    	{
    		private Socket listenSocket = null;			//Listen-Socket
    		private Socket clientSocket = null;			//Client-Socket
    //		private Socket listenclient = null;			//Client-Socket
    
    		private Thread m_rec_thread;				//Thread der den listenSocket verwendet und auf antwort vom kopller lauscht
    		private Thread m_send_thread;				//Thread der zum senden der Telegramme verwendet wird
    		private IPEndPoint endpoint;				//Remoteendpoint wohin soll sich der server verbindne
    
    		//___________________Konstanten füe die Werte_________________
    		public static readonly string REMOTE_IP = "REMOTE_IP";
    		public static readonly string REMOTE_PORT = "REMOTE_PORT";		//44445
    		public static readonly string LOCAL_PORT = "LOCAL_PORT";		//44444
    
    		//___________________Array mit benötigten werten______________
    		private static readonly string[] allowedkeys = new string[]		{REMOTE_IP,REMOTE_PORT,LOCAL_PORT};
    
    		public new delegate void FactorialCompleteHandler(Telegramm t);
    		public new event FactorialCompleteHandler FactorialComplete;
    
    		public override void start()
    		{
    			base.start ();
    			//________________________Socket-Server________________________________
    
    			// Listen-Socket erzeugen und auf Lauschposten setzen
    			try 
    			{
    				try
    				{
    					this.listenSocket.Close();
    				}
    				catch(Exception e)
    				{
    					Console.WriteLine(e.Message);
    				}
    					// erzeugen
    				this.listenSocket = new Socket(AddressFamily.InterNetwork, 
    					SocketType.Stream, 
    					ProtocolType.Tcp);
    
    				// binden
    				this.listenSocket.Bind(endpoint);
    
    				// Listen-Modus mit maximaler Anzahl Clients
    				this.listenSocket.Listen(100);
    
    			}	// try Socket-Erzeugung
    			catch (Exception ex)
    			{
    				Console.WriteLine("Fehler in SocketCommunicationComponent --> ListenSocket: \n " + ex.Message);
    			}
    
    			//_______________________Ende-Socket-Server______________________________
    			try
    			{
    
    				m_status = AbstractCommunicationComponent.DISCONNECTED;
    				//_______________________Socket-Client___________________________________
    
    				//erstellen eines sockets ...
    				this.clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
    				String szIPSelected  = this.Parameter[REMOTE_IP].ToString();
    				int  alPort = Convert.ToInt32(this.Parameter[REMOTE_PORT]);
    
    				System.Net.IPAddress	remoteIPAddress	 = System.Net.IPAddress.Parse(szIPSelected);
    				System.Net.IPEndPoint	remoteEndPoint = new System.Net.IPEndPoint(remoteIPAddress, alPort);
    				//Verbindung herstellen...
    				clientSocket.Connect(remoteEndPoint);
    				m_status = AbstractCommunicationComponent.CONNECTED;
    				//_______________________Ende-Socket-Client______________________________
    
    				// create threads
    				m_rec_thread = new Thread(new ThreadStart(this.receiveThread));
    				m_rec_thread.Name="Empfangsthread";
    				m_rec_thread.Start();
    			}
    			catch
    			{
    				m_status = AbstractCommunicationComponent.DISCONNECTED;
    			}
    		}
    
    		/// <summary>
    		/// Get the new data and send it out to all other connections. 
    		/// Note: If not data was recieved the connection has probably 
    		/// died.
    		/// </summary>
    		/// <param name="ar"></param>
    		public void OnRecievedData( IAsyncResult ar )
    		{
    			SocketClient client = (SocketClient)ar.AsyncState;
    			byte [] aryRet = client.GetRecievedData( ar );
    			if(this.m_running == true)
    			{
    				// If no data was recieved then the connection is probably dead
    				if( aryRet.Length < 1 )
    				{
    					Console.WriteLine( "Client {0}, disconnected", client.Sock.RemoteEndPoint );
    					Thread.Sleep(250);
    					//client.Sock.Close();    				
    					//return;
    				}
    				else
    				{
    					//string inData		= .ToString();						// Client-Anfrage als String
    					m_status = AbstractCommunicationComponent.CONNECTED;	//setzt den Verbindungsstatus
    
    					// Empfangene Zeichen von BYTE in String umwandeln
    					char[]	chars	= new char[aryRet.Length];
    					Decoder	dec		= Encoding.UTF8.GetDecoder();
    					int		charLen	= dec.GetChars(aryRet, 0, aryRet.Length, chars, 0);
    					string inData			= new String(chars);
    
    					// überflüssige Leerzeichen abschneiden
    					inData	= inData.Trim();
    					receiveTelegramm(inData);
    					Console.WriteLine(inData);
    
    				}
    				client.SetupRecieveCallback( this );
    			}
    			else
    			{
    				client.Sock.Shutdown(SocketShutdown.Both);
    				client.Sock.Close();
    				//return;
    			}
    		}
    
    		public override void stop()
    		{
    			base.stop();
    			//if(m_rec_thread != null)
    			//{
    				try
    				{
    					//this.listenSocket.Close();
    					this.listenSocket.Shutdown(SocketShutdown.Both);
    				}
    				catch(Exception e)
    				{
    					Console.Error.WriteLine("Fehler in SocketCommunicationComponent1 --> stop"+e.Message);
    				}
    			try
    			{
    				this.clientSocket.Shutdown(SocketShutdown.Both);
    				this.clientSocket.Close();
    			}
    			catch(Exception ex)
    			{
    				Console.Error.WriteLine("Fehler in SocketCommunicationComponent2 --> stop"+ex.Message);
    			}
    					//Console.WriteLine(m_running);
    				//m_rec_thread.Abort();
    				//m_rec_thread.Interrupt();
    				//m_rec_thread.IsAlive = false;
    				//m_rec_thread.Suspend();
    				//Console.WriteLine(m_rec_thread.ThreadState);
    				//Console.WriteLine(m_rec_thread.IsAlive);
    			//}
    			m_status = AbstractCommunicationComponent.DISCONNECTED;
    
    		}
    		/// <summary>
    		/// Konstruktor der SocketCommunicationComponent class 
    		/// </summary>
    		/// <param name="sps">SPS Referenz</param>
    		public SocketCommunicationComponent(SPS sps):base(sps)
    		{
    			// IPEndPoint mit allen IP-Adressen und dem festgelegten Port initialisieren
    			endpoint = new IPEndPoint(IPAddress.Any, Convert.ToInt32(this.Parameter[LOCAL_PORT]) );
    			start();			
    		}
    
    		/// <summary>
    		/// Thread der den listenSocket verwendet und ein Telegramm mit vorrausgehenden 
    		/// Zeitstempel enthält.
    		/// </summary>
    		public void receiveThread()
    		{
    			// anfragenden Client entgegennehmen	
    			// Send operations will time-out if confirmation 
    			// is not received within 1000 milliseconds.
    
    				this.listenSocket.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 100);
    				this.listenSocket.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100);
    				this.listenSocket.SetSocketOption (SocketOptionLevel.Socket ,SocketOptionName.NoDelay,1);
    				this.listenSocket.BeginAccept(new AsyncCallback( OnConnectionRequest ), this.listenSocket );
    
    				while(m_running)				//solange der Parameter der Super klasse true ist
    				{
    					Thread.Sleep(100);
    				}
    				m_status = AbstractCommunicationComponent.DISCONNECTED;	//setzt den Verbindungsstatus
    
    			try{
    				Console.WriteLine("Available : "+this.listenSocket.Available);
    				this.listenSocket.Shutdown(SocketShutdown.Both);
    			}
    			catch(Exception a){
    				Console.Error.WriteLine("Fehler im listen Thread1 --->"+a.Message);
    			}
    			try
    			{
    				this.listenSocket.Close();
    				//this.listenSocket.Shutdown(SocketShutdown.Receive);
    			}
    			catch(Exception e)
    			{
    				Console.Error.WriteLine("Fehler im listen Thread --->"+e.Message );
    			}
    			GC.Collect();
    			GC.WaitForPendingFinalizers();	
    			//this.listenSocket.EndAccept();
    		}
    		/// <summary>
    		/// Get the new data and send it out to all other connections. 
    		/// Note: If not data was recieved the connection has probably 
    		/// died.
    		/// </summary>
    		/// <param name="ar"></param>
    		public void OnConnectionRequest( IAsyncResult ar )
    		{
    			Socket listenclient1 = (Socket)ar.AsyncState;
    			Socket s = null;
    			SocketClient client;
    			if(this.m_running == true)
    			{
    				try
    				{
    					s = listenclient1.EndAccept(ar);
    				}
    				catch(Exception e)
    				{
    					Console.Error.WriteLine("Fehler in SocketCommunicationComponent --> ListenClient.EndAccept \n"+e.Message );
    				}
    				if(s == null)
    				{
    					Console.Error.WriteLine("Fehler in SocketCommunicationComponent --> Socket nicht initialisiert");
    				}
    				else
    				{
    					client = new SocketClient(s);
    					client.SetupRecieveCallback(this);				
    				}
    				listenclient1.BeginAccept(new AsyncCallback( OnConnectionRequest ), listenclient1 );
    			}
    			else
    			{
    				try
    				{
    					Console.WriteLine("Available : "+this.listenSocket.Available);
    					listenclient1.Shutdown(SocketShutdown.Both);
    				}
    				catch(Exception a)
    				{
    					Console.Error.WriteLine("Fehler im OnConnectionRequest --->"+a.Message);
    				}
    				try
    				{
    					listenclient1.Close();
    					//this.listenSocket.Shutdown(SocketShutdown.Receive);
    				}
    				catch(Exception e)
    				{
    					Console.Error.WriteLine("Fehler im OnConnectionRequest --->"+e.Message );
    				}
    				//listenclient1.Close();
    				//listenclient1.Shutdown(SocketShutdown.Both);
    			}
    		}
    		/// <summary>
    		/// This function has to be executed, when a new telegramm (string) arrives.
    		/// A new Telegramm (class) will be created and will be send to the responible SPS-Class
    		/// </summary>
    		/// <param name="t">the received telegramm (string)</param>
    		public override void  receiveTelegramm(string t) // Interface-methode
    		{
    			if (t=="")return;
    			Telegramm teleg = m_sps.TelegrammBuilder.getSIMTelegramm(t.Substring(23,t.Length-23));
    
    			if(teleg!=null)
    			{
    				//teleg.setProperty(Telegramm.TIMESTAMP,t.Substring(0,23));
    				teleg.TimeStamp=t.Substring(0,23);
    				FactorialComplete(teleg);
    
    				m_sps.receiveTelegramm(teleg);
    				//m_sps.SimulationKernel.TelegrammPool.add(teleg);
    
    			}
    			else
    			{
    				TelegrammDefinition unknownT = new TelegrammDefinition();
    				unknownT.Type="unknown";
    				teleg=new Telegramm(unknownT);
    				teleg.TimeStamp=t.Substring(0,23);
    				teleg.TelegrammText=t.Substring(23,t.Length-23);
    				teleg.Sps=this.m_sps;
    				FactorialComplete(teleg);
    			}
    		}
    
    		public override string sendDirectTelegramm( string t )
    		{
    			string inData		= "";						// Client-Anfrage als String
    
    			try
    			{
    				string teleg_str = t;
    
    				if (teleg_str != "")
    				{
    					teleg_str=teleg_str.PadRight(100,'y'); // auf 100 Zeichen erweitern
    
    					byte[] byData = System.Text.Encoding.ASCII.GetBytes(teleg_str + "\n");
    					int i = clientSocket.Send(byData);
    					int		inBytes		= 0;						// Zähler empfangene Bytes
    					byte[] buffer = new byte[1024];
    
    					// Empfangen der Client-Anfrage
    					if((inBytes = clientSocket.Receive(buffer)) > 0)
    					{
    						// Daten wurden empfangen --> Auswerten der Empfangenen Anfrage
    						if (buffer != null) 
    						{
    							// Empfangene Zeichen von BYTE in String umwandeln
    							char[]	chars	= new char[inBytes];
    							Decoder	dec		= Encoding.UTF8.GetDecoder();
    							int		charLen	= dec.GetChars(buffer, 0, inBytes, chars, 0);
    							inData			= new String(chars);
    
    							// überflüssige Leerzeichen abschneiden
    							inData	= inData.Trim();
    							//teleg.setProperty(Telegramm.TIMESTAMP,inData.Substring(0,23));
    							if(inData.Substring(23,inData.Length-23)!=teleg_str)//überprüfen ob empfangenes Telegramm
    								//mit gesendetem telegramm übereinstimmt.
    							{
    								Console.Error.WriteLine("Fehler in SocketCommunicationComponent --> Zeitstempel für falsches Telegramm empfangen");
    							}
    							Console.WriteLine(inData);
    						}
    					}
    				}
    			}
    			catch(Exception ex){
    				Console.Error.WriteLine("Fehler in SocketCommunicationComponent -> SendDirectTelegramm \n"+ex.Message);
    			}
    
    			return inData;
    		}
    
    		/// <summary>
    		/// Sends a Telegramm and adds a time stamp after the Telegramm is successfully sent.
    		/// </summary>
    		/// <param name="t">The Telegramm to send</param>
    		public override void sendTelegramm( Telegramm t)
    		{
    			lock(m_outQueue)
    			{
    				m_outQueue.Enqueue(t);
    			}
    			m_send_thread = new Thread(new ThreadStart(this.sendThread));
    			m_send_thread.Name="sendeThread gesendet";
    			m_send_thread.Start();
    		}
    
    		/// <summary>
    		/// Thread zum sender der telegrammdaten per Socket
    		/// </summary>
    		public void sendThread()
    		{
    			try
    			{
    				Telegramm teleg;
    				string teleg_str;
    
    				//loop over all entries!
    				while(m_outQueue.Count > 0 && m_running)
    				{
    					teleg = null;
    					teleg_str="";
    
    					lock(m_outQueue)
    					{
    						if(m_outQueue.Count > 0)
    						{
    							teleg = (Telegramm) m_outQueue.Dequeue();
    							teleg_str = m_sps.TelegrammBuilder.getSPSTelegramm(teleg);
    						}
    					}
    
    					if (teleg!=null)
    					{
    						teleg_str=teleg_str.PadRight(100,'x');
    						byte[] byData = System.Text.Encoding.ASCII.GetBytes(teleg_str + "\n");
    						lock(clientSocket)
    						{
    							int i = clientSocket.Send(byData);
    							int		inBytes		= 0;						// Zähler empfangene Bytes
    							byte[] buffer = new byte[1024];
    							string inData		= "";						// Client-Anfrage als String
    
    							// Empfangen der Client-Anfrage
    							if((inBytes = clientSocket.Receive(buffer)) > 0)
    							{
    								// Daten wurden empfangen --> Auswerten der Empfangenen Anfrage
    								if (buffer != null) 
    								{
    									// Empfangene Zeichen von BYTE in String umwandeln
    									char[]	chars	= new char[inBytes];
    									Decoder	dec		= Encoding.UTF8.GetDecoder();
    									int		charLen	= dec.GetChars(buffer, 0, inBytes, chars, 0);
    									inData			= new String(chars);
    
    									// überflüssige Leerzeichen abschneiden
    									inData	= inData.Trim();
    									teleg.setProperty(Telegramm.TIMESTAMP,inData.Substring(0,23));
    									teleg.TimeStamp=inData.Substring(0,23);
    									//m_sps.SimulationKernel.TelegrammPool.add(teleg);
    									FactorialComplete(teleg);
    
    									if(inData.Substring(23,inData.Length-23)!=teleg_str)//überprüfen ob empfangenes Telegramm
    										//mit gesendetem telegramm übereinstimmt.
    									{
    										Console.Error.WriteLine("Fehler in SocketCommunicationComponent --> *********++++++++########Fehler########++++++++*********");
    									}
    									Console.WriteLine(inData);
    								}
    							}
    						}
    					}
    				}
    			}
    			catch(Exception ex)
    			{
    				Console.WriteLine("Fehler in SocketCommunicationComponent --> "+ex.Message);
    			}
    		}
    	}
    }
    
    using System;
    using System.Net.Sockets;
    
    namespace SSIM2
    {
    	/// <summary>
    	/// Class holding information and buffers for the Client socket connection
    	/// </summary>
    	public class SocketClient
    	{
    		private Socket m_sock;						// Connection to the client
    		private byte[] m_byBuff = new byte[1024];		// Receive data buffer
    		/// <summary>
    		/// Constructor
    		/// </summary>
    		/// <param name="sock">client socket conneciton this object represents</param>
    		public SocketClient( Socket sock )
    		{
    			m_sock = sock;
    		}
    
    		// Readonly access
    		public Socket Sock
    		{
    			get{ return m_sock; }
    		}
    
    		/// <summary>
    		/// Setup the callback for recieved data and loss of conneciton
    		/// </summary>
    		/// <param name="app"></param>
    		public void SetupRecieveCallback( SocketCommunicationComponent scc )
    		{
    			try
    			{
    				AsyncCallback recieveData = new AsyncCallback(scc.OnRecievedData);
    				m_sock.BeginReceive( m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, this );
    			}
    			catch( Exception ex )
    			{
    				Console.WriteLine( "Recieve callback setup failed! {0}", ex.Message );
    			}
    		}
    
    		/// <summary>
    		/// Data has been recieved so we shall put it in an array and
    		/// return it.
    		/// </summary>
    		/// <param name="ar"></param>
    		/// <returns>Array of bytes containing the received data</returns>
    		public byte [] GetRecievedData( IAsyncResult ar )
    		{
    			int nBytesRec = 0;
    			try
    			{
    				nBytesRec = m_sock.EndReceive( ar );
    			}
    			catch{}
    			byte [] byReturn = new byte[nBytesRec];
    			Array.Copy( m_byBuff, byReturn, nBytesRec );
    
    			// Check for any remaining data and display it
    			// This will improve performance for large packets 
    			// but adds nothing to readability and is not essential
    			int nToBeRead = m_sock.Available;
    			if( nToBeRead > 0 )
    			{
    				byte [] byData = new byte[nToBeRead];
    				m_sock.Receive( byData );
    				// Append byData to byReturn here
    			}
    
    			return byReturn;
    		}
    	}
    }
    

    Vielleicht hat ja jemand schon mal das gleiche Problem gehabt und kann mir helfen

    mfg finalmove


Anmelden zum Antworten