Autor Beitrag
PC17
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37



BeitragVerfasst: Sa 03.07.10 19:08 
löschen
Einloggen, um Attachments anzusehen!


Zuletzt bearbeitet von PC17 am Fr 02.04.21 11:06, insgesamt 1-mal bearbeitet
MoBBer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37
Erhaltene Danke: 1



BeitragVerfasst: So 04.07.10 17:31 
Hallo PC17,

anscheinend wird dein Socket-Objekt server automatisch verworfen wenn die Eigenschaft Connected flase gesetzt wird.
Du musst dein Socket-Objekt also immer beim Verbinden neu erstellen.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
private void btnOpen_Click(object sender, EventArgs e)
        {
            if (!server.Connected)
                try
                {
                    server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    
                    server.Connect(ipEndPoint);
                    WriteLine("Connected to Server!");

                    var listener = new Thread(Listen);
                    listener.Priority = ThreadPriority.Lowest;
                    listener.Start();
                }
                catch (Exception exception)
                {
                    WriteLine(exception.Message);
                }
        }
PC17 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37



BeitragVerfasst: So 04.07.10 17:53 
Aber wenn ich den Button klicke wird es ja eh erstellt oder wie meinst du ?
Kannst du bitte den Code so posten wie ich ihn ändern muss das ich mich wiederverbinden kann, DANKE.
MoBBer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37
Erhaltene Danke: 1



BeitragVerfasst: So 04.07.10 17:55 
Ich habe den geänderten Code gepostet, die markierte Zeile habe ich dort eingefügt.
Hätte ich vielleicht un Missverständnisse zu vermeiden drüber schreiben sollen. :D
PC17 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37



BeitragVerfasst: So 04.07.10 18:06 
Sorry, hatte gerade den Code nicht vor mir. ;)
Danke noch mal werde ich gleich mal testen.
PC17 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37



BeitragVerfasst: So 04.07.10 18:19 
Also einen Schritt bin ich weiter gekommen.
Aber wenn ich die Verbindung trenne wird der Server sofort zu gemacht und das muss man doch irgendwie verhindern können?
Jetzt kommt als Fehlermeldung:
Verbindung fehlgeschlagen: Es konnte keine Verbindung hergestellt werden, da der Zielcomputer die Verbindung verweigerte 127.0.0.1:9050

@MoBBer: Hast du dich wiederverbinden können?
MoBBer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37
Erhaltene Danke: 1



BeitragVerfasst: So 04.07.10 18:27 
Ja ich konnte mich wieder verbienden allerdings habe ich einfach nur den Server neu gestartet.

Das sich der Server schließt liegt daran, dass der Client eine 0 sendet wenn er die Verbindung trennt.
Und in dem Fall wird das Programm einfach bis zum Schluss abgearbeitet.

Du müsstest dir eine Endlosschleife bauen die die Anfragen zum Verbinden entgegen nimmt und die einzelnen Threads zum schreiben startet.
PC17 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37



BeitragVerfasst: So 04.07.10 18:35 
Ja so kann ich mich auch wieder verbinden. Aber ich möchte ja bei dem einen Server die Verbindung trennen und die Verbundung zu einen anderen aufbauen und später wieder zu den alten zurück verbinden. Also einfach trennen und wieder verbinden.

Meinst du das ich einen Endlossschleife über den Server machen soll(while Schleife)?
MoBBer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37
Erhaltene Danke: 1



BeitragVerfasst: So 04.07.10 18:59 
Ja du musst bei deinem Server die Verbindungslogik in eine Endlosschleife schreiben und in der Methode Listen darfst du den Listener nicht stoppen.



Main-Methode, die markierten Zeilen sind hinzuzufügen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
data = new byte[1024];
var localAddress = IPAddress.Any;
tcpListener = new TcpListener(localAddress, 9050);
tcpListener.Start();
Console.WriteLine("I'am the TCP Server!");
Console.WriteLine("Waiting for a client...");

while (true)
{

    tcpClient = tcpListener.AcceptTcpClient();
    networkStream = tcpClient.GetStream();

    data = "Welcome to TCP Server!".ToByteArray();
    networkStream.Write(data, 0, data.Length);

    var listener = new Thread(Listen);
    listener.Priority = ThreadPriority.Lowest;
    listener.Start();
}


Listen-Methode, markierte Zeile ist zu löschen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
while (true)
{
    data = new byte[1024];
    received = networkStream.Read(data, 0, data.Length);
    if (received == 0)
       break;

    string get = Encoding.ASCII.GetString(data, 0, received);
    var send = get.ToByteArray();
    Console.WriteLine("Received from TCP Client: " + get);
    networkStream.Write(send, 0, send.Length);
}

networkStream.Close();
tcpClient.Close();
tcpListener.Stop();


So läuft der Server immer weiter und du kannst dich munter drauf verbinden und trennen.


Zuletzt bearbeitet von MoBBer am So 04.07.10 19:01, insgesamt 1-mal bearbeitet
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 04.07.10 19:00 
Ich hab ja von dem Netzwerk-Kram wenig Ahnung, aber produziert die Endlos-Schleife nicht ne Menge Threads, die nie gestoppt werden? :gruebel:

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
MoBBer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37
Erhaltene Danke: 1



BeitragVerfasst: So 04.07.10 19:08 
Ja das stimmt man sollte den erstellten Thread am ende des Chats wieder beenden.

Allerdings wird ein neuer Thread ja immer nur erstellt wenn sich ein Client verbindet und momentan kann sich nur ein Client verbinden.
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 04.07.10 19:17 
Ich hab mir das jetzt mal genauer angesehen und denke, die Erstellung von Threads in einer Endlos-Schleife ist nicht nötig. Um das Beenden des Servers zu verhindern, reicht doch ein einfaches Console.ReadLine().

Der ganze Sinn von Threads ist doch gerade, ein Programm nicht zu blockieren. Ein Programm dadurch zu blockieren, dass man am laufenden Band Threads erstellt mutet irgendwie sehr komisch an.

So scheint es zu funktionieren:
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:
    private static byte[] data;
    private static NetworkStream networkStream;
    private static int received;
    private static TcpClient tcpClient;
    private static TcpListener tcpListener;
    private static volatile bool running;

    public static void Main()
    {
        data = new byte[1024];
        var localAddress = IPAddress.Any;
        tcpListener = new TcpListener(localAddress, 9050);
        tcpListener.Start();
        Console.WriteLine("I'am the TCP Server!");
        Console.WriteLine("Waiting for a client...");

        tcpClient = tcpListener.AcceptTcpClient();
        networkStream = tcpClient.GetStream();
        
        data = "Welcome to TCP Server!".ToByteArray();
        networkStream.Write(data, 0, data.Length);

        var listener = new Thread(Listen);
        listener.Priority = ThreadPriority.Lowest;
        running = true;
        listener.Start();


        Console.ReadLine();
        running = false;

    }

    static void Listen()
    {
        
        while (running)
        {
            data = new byte[1024];
            received = networkStream.Read(data, 0, data.Length);
            if (received > 0)
            {

                string get = Encoding.ASCII.GetString(data, 0, received);
                var send = get.ToByteArray();
                Console.WriteLine("Received from TCP Client: " + get);
                networkStream.Write(send, 0, send.Length);
            }
        }
        networkStream.Close();
        tcpClient.Close();
        tcpListener.Stop();
    }

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
PC17 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37



BeitragVerfasst: So 04.07.10 19:21 
Okay, danke für eure Hilfe

Wenn einige Threads endlos dahin laufen ist es auch egal mehr wie zu 4 Server werde ich mich nicht verbinden.
MoBBer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37
Erhaltene Danke: 1



BeitragVerfasst: So 04.07.10 19:36 
@ Christian S.: so funktioniert das nicht die Listen-Methode an sich soll nicht unendlich weiter laufen.
Deine Umstellung auf "if (received > 0)" hat zur folge das sich ein Client nicht mehr von Server trennen kann.

Es geht darum das der TCPListener immer weiter laufen muss, damit sich der Client nach dem Trennen nocheinmal verbinden kann und genau das bewirkt meine Endlosschleife.

In meiner Endlosschleife werden nicht unzählige Threads erstellt da die Zeile

"tcpClient = tcpListener.AcceptTcpClient();"

bewirkt, dass die Ausführung stoppt bis sich ein Client bei dem Server meldet. Die Endlosschleife pausiert so zu sagen.

@PC17: Du sollest mal dieses Tutorial durcharbeiten und auch deinen Chat-Server/Client anpassen

mfg MoBBer


Zuletzt bearbeitet von MoBBer am So 04.07.10 19:48, insgesamt 2-mal bearbeitet
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 04.07.10 19:40 
Ja, user profile iconKha wies mich auch gerade drauf hin. Das mit dem AcceptTcpClient habe ich übersehen.

Aber ist es nicht sinnvoll, einen Verbindung zu halten, so lange sie gebraucht wird, anstatt immer wieder neu zu verbinden? :gruebel:

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
MoBBer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37
Erhaltene Danke: 1



BeitragVerfasst: So 04.07.10 19:42 
Ja sicher, aber "received == 0" bedeutet, dass der Client die Verbindung getrennt hat und damit man die Verbindung wiederaufnehmen kann muss der TCPListener weiterlaufen und auf Clients warten. Desweiteren ist das der Grundstein damit später auf seinem Server mehrere Leute gleichzeitig angemeldet sein können und mit einander chatten können.

Für diesen Beitrag haben gedankt: Christian S.
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 04.07.10 19:45 
Ah, okay. :idea:

Ich glaube, ich warte mit dem Netzwerk-Kram, bis der ganze Schleifenkram weggekapselt ist. Bei Windows muss man sich ja auch nicht mehr mit der Schleife zur Nachrichtenverarbeitung rumschlagen :mrgreen:

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: So 04.07.10 20:20 
Kein Problem, ich biete Rekursion an :mrgreen: .
Es sollte möglich sein, die Kommunikation über BeginAcceptTcpClient, BeginRead und BeginWrite komplett asynchron zu gestalten, wie ich das hier schon einmal mit Accept versucht habe. Damit wird also nur ein Thread benötigt, wenn sich ein neuer Client verbindet oder eine Anfrage bearbeitet wird. Wartende Threads gibt es überhaupt nicht mehr.

Muss mir mal anschauen, ob die TPL das noch etwas hübscher hinbekommen würde :gruebel: .

_________________
>λ=
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 05.07.10 22:35 
Die erste Version ist keine großartige Verbesserung, aber die zweite muss sich imo nicht einmal hinter den Async Expressions von F# verstecken.

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:
static class TcpListenerEx
{
  public static Task<TcpClient> AcceptTcpClientAsync(this TcpListener self)
  {
    return Task<TcpClient>.Factory.FromAsync(self.BeginAcceptTcpClient, self.EndAcceptTcpClient, state: null);
  }
}

void AcceptClients()
{
  listener.AcceptTcpClientAsync().ContinueWith(client => {
      HandleClient(client.Result);
      AcceptClients();
  });
}

void HandleClient(TcpClient tcpClient)
{
  Stream stream = tcpClient.GetStream();
  var buffer = new byte[140];
  // Aus ParallelExtensionExtras, http://blogs.msdn.com/b/pfxteam/archive/2010/04/04/9990342.aspx
  stream.ReadAsync(buffer, 0, buffer.Length).ContinueWith(read => {
    if (read.Result > 0)
      stream.WriteAsync(buffer.Reverse().ToArray(), 0, buffer.Length).ContinueWith(_ =>
        HandleClient(tcpClient)
      );
  });
}

void AcceptClients2()
{
  // Ebenfalls ParallelExtensionExtras, siehe http://blogs.msdn.com/b/pfxteam/archive/2009/06/30/9809774.aspx
  Task.Factory.Iterate(this.AcceptClients2Loop());
}

IEnumerable<Task> AcceptClients2Loop()
{
  while (true)
  {
    var client = listener.AcceptTcpClientAsync();
    yield return client;
    Task.Factory.Iterate(HandleClient2(client.Result));
  }
}

IEnumerable<Task> HandleClient2(TcpClient tcpClient)
{
  Stream stream = tcpClient.GetStream();
  var buffer = new byte[140];

  while (true) {
    var read = stream.ReadAsync(buffer, 0, buffer.Length);
    yield return read;
    if (read.Result == 0)
      break;
    yield return stream.WriteAsync(buffer.Reverse().ToArray(), 0, buffer.Length);
  }
}


Achja, alles ungetestet ;) .

_________________
>λ=
PC17 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 37



BeitragVerfasst: Di 13.07.10 20:26 
Habe da noch einen anderen Server and Client gefunden ist leider nur ein code und habe ihn noch nicht getestet und jetzt stehe ich beim TCPListener an.

Das ist die Listen Methode von dem oben genannten Client:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
private void Listen()
        {
            var recv = server.Receive(data);
            stringData = Encoding.ASCII.GetString(data, 0, recv);
            WriteLine(stringData);

            while (server.Connected)
            {
                data = new byte[1024];
                recv = server.Receive(data);
                stringData = Encoding.ASCII.GetString(data, 0, recv);
                WriteLine("Received from Server: " + stringData);
            }
            WriteLine("Disconnecting from server...");
            server.Close();
        }




Möchte einfach die neue Methode StartListen() zu der alten Listen() hinzufügen das ich mich über die Methode Listen verbinden und halt dann der alte Server and Client läuft und auch die Methode RunClient ausgeführt wird.
Ich bringe es dann nicht zusammen das ich socketForServer,IPEndPoint vom neuen Client im alten einbaue. Vl kann mir jemand helfen, falls es noch fragen gibt bitte melden.

MfG PC17


Zuletzt bearbeitet von PC17 am So 18.07.10 20:11, insgesamt 1-mal bearbeitet