F
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