Hallo,
ich habe mir das Tutorial "Client-/Server-Komponente über TCP-Sockets" hier auf der Seite gerade angeschaut und wollte diesen Code für mich Optimieren.
Bissher habe ich diesem Code:
/// <summary>
/// Zusammenfassung für den Server
/// </summary>
public class Server
{
/// <summary>
/// Port, auf dem der Server auf Clientverbindungen wartet
/// </summary>
public const int serverListenPort = 10000;
/// <summary>
/// Anzahl Millisekunden in Warteschleifen
/// </summary>
public const int sleepTime = 200;
/// <summary>
/// Der Haupt-Thread
/// </summary>
private Thread mainThread;
/// <summary>
/// IP-Adresse, an der auf Verbindungen gewartet werden soll.
/// Standardmässig wird auf allen Schnittstellen gewartet.
/// </summary>
public IPAddress ipAddress = IPAddress.Any;
/// <summary>
/// Der Standardkonstruktor richtet den Thread ein, welcher
/// anschliessend auf Client-Verbindungen wartet.
/// </summary>
public Server()
{
// Hauptthread wird instanziiert ...
mainThread = new Thread(new ThreadStart(this.mainListener));
// ... und gestartet
mainThread.Start();
}
/// <summary>
/// Haupt-Thread, wartet auf neue Client-Verbindungen
/// </summary>
private void mainListener()
{
// Alle Netzwerk-Schnittstellen abhören
TcpListener listener = new TcpListener(ipAddress, serverListenPort);
System.Console.WriteLine("Listening on port " + serverListenPort + "...");
try
{
// Verbindungsannahme aktivieren
listener.Start();
// Warten auf Verbindung
while (!listener.Pending()) { Thread.Sleep(sleepTime); }
// Verbindung annehmen
Socket newSocket = listener.AcceptSocket();
// Mitteilung bzgl. neuer Clientverbindung
System.Console.WriteLine("Neue Client-Verbindung (" +
"IP: " + newSocket.RemoteEndPoint + ", " +
"Port " + ((IPEndPoint)newSocket.LocalEndPoint).Port.ToString() + ")");
}
catch (Exception ex)
{
throw new Exception("Fehler bei Verbindungserkennung", ex);
}
}
}
Ich möchte nun aber den Server starten und dann soll er laufen, bis man ihn wieder manuell schließt. Quasi eine Endlosschleife. Zuerst möchte ich, dass das ganze mit einer Verbindung stabil funktioniert.
Wie bekomme ich das hin?
Edit:
Habe jetzt
for (; ; ){...}
genommen.
--
Vielen Dank
LG
Kevin
Deine in den Startbeitrag hinein editierte Lösung ist nicht gerade sauber.
Ich sehe am Code Deines Servers auch nicht, wieso es nicht dauerhaft laufen sollte.
Vermutlich ist es ein Fehler, wie Du die Server-Klasse nutzt.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hi Abt,
ich erstelle einfach beim Programmstart ein Objekt von der Server Klasse.
Mehr passiert hier nicht. Wenn der Client geschlossen wird, schließt sich der Server.
--
Vielen Dank
LG
Kevin
Das Grundproblem liegt aus meiner Sicht darin, dass du nur einen Client annimmst. Wenn der Client disconnected wird auch dein Thread verlassen. - Bisher dacht ich immer, dass das vorher schon passiert - Aber vielleicht ist es ja auch so.
Wie sieht denn deine Program.cs aus?
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
So:
Das Sleep ist einfach nur drin, dass ich seh was in der Console steht, bevor der Server beendet wird.
class Program
{
static void Main(string[] args)
{
Server srv = new Server();
System.Threading.Thread.Sleep(10000);
}
}
--
Vielen Dank
LG
Kevin
Schön wäre es, wenn du deine Lösung noch posten würdest.
// EDIT
Statt dem Thread.Sleep() solltest du eher Console.ReadLine() oder ähnliches verwenden. Dann bleibts auch stehen, wenn du mal abgelenkt bist. 😃
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Edit:
Habe jetztfor (; ; ){...}
genommen.
Die Lösung steht schon im Startthread.
Das Sleep kommt auch wieder raus, war nur zu Testzwecken.
--
Vielen Dank
LG
Kevin
Ich versteh die Lösung nicht. - Also denke ich, wird auch kein anderer wissen was du nun mit der For-Schleife anfängst.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Die Lösung ist einfach eine Endlosschleife.
public void Process()
{
MySQL mysql = new MySQL();
DateTime now = DateTime.Now;
MemoryStream mem = new MemoryStream();// Empfangspuffer
byte[] buffer = new byte[BufferSize];
int TimeOut = 0;
instanceOfClass.newMessage("Server gestartet");
//while (TimeOut < (10 * 1000 / SleepTime))
for (; ; )
{
//Console.WriteLine("1 - jhadbfhibsdb");
mem.Seek(0, SeekOrigin.Begin);
mem.SetLength(0);
while (socket.Available > 0)
{
//Console.WriteLine("2 - jhadbfhibsdb");
//Byte[] buffer = new byte[bytesAvailable];
int bytesRead = socket.Receive(buffer, buffer.Length, SocketFlags.None);
if (bytesRead <= 0) continue;
mem.Write(buffer, 0, bytesRead);
//instanceOfClass.Receive(buffer);
// Alles zurücksetzen
}
if (mem.Length > 0)
{
//Console.WriteLine("3 - jhadbfhibsdb");
//if (System.Text.Encoding.ASCII.GetString(mem.ToArray(), 0, 4) == "quit")
//{
// instanceOfClass.closeConnection();
// //socket.Close();
// Console.WriteLine("Client (" + socket.RemoteEndPoint + ") wurde vom Server getrennt.");
//}
if (System.Text.Encoding.ASCII.GetString(mem.ToArray(), 0, 9) == "newvendor")
{
string stream = System.Text.Encoding.ASCII.GetString(mem.ToArray());
string[] split = stream.Split(new Char[] { '|' });
mysql.insertVendor(split[1], split[2], split[3], split[4]);
Console.WriteLine("Ein neuer Lieferant (" + split[1] + ") wurde angelegt. " + now.ToString("dd.MM.yyyy HH:mm"));
instanceOfClass.Send(System.Text.Encoding.ASCII.GetBytes("erfolgreich"));
}
else if (System.Text.Encoding.ASCII.GetString(mem.ToArray(), 0, 17) == "insertordernumber")
{
string stream = System.Text.Encoding.ASCII.GetString(mem.ToArray());
string[] split = stream.Split(new Char[] { '|' });
mysql.insertIntoDatabase(split[1], split[2]);
Console.WriteLine("Der Artikel (" + split[1] + ") wurde für den Lieferant (" + split[2] + ") hinzugefügt. " + now.ToString("dd.MM.yyyy HH:mm"));
instanceOfClass.Send(System.Text.Encoding.ASCII.GetBytes("erfolgreich"));
}
//Console.WriteLine("send {0} bytes",mem.Length);
//instanceOfClass.Receive(mem.ToArray());
mem.Seek(0, SeekOrigin.Begin);
mem.SetLength(0);
TimeOut = 0;
//Console.WriteLine("4 - jhadbfhibsdb");
}
else
{
TimeOut++;
Thread.Sleep(SleepTime);
}
}
instanceOfClass.closeConnection();
socket.Close();
socket = null;
serverThread.Abort();
}
--
Vielen Dank
LG
Kevin
Statt for(;;) würde ich eher sowas wie while(!shutdown) nehmen, dann kannst du den Server auch gezielt beenden indem du das shutdown flag setzt. Ansonsten passts doch. Der ganze Kram in if (mem.Length > 0) geht auch einfacher, wenn Du einen TcpListener / TcpClient und dazu StreamReader/StreamWriter verwendest.