2016-06-25 7 views
1

Ich habe an einem TCP NAT Punch-Through-Server/Client-Chat-Raum-Setup gearbeitet. Ich habe es erfolgreich in UDP eingerichtet und jetzt möchte ich dasselbe für TCP tun, da ich ein bisschen rauh auf meinen Sockeln bin.Multi-Thread-TCP-Server-Echo zurück zu allen Clients

Alle möglichen Verbindungen zwischen den Clients und dem Chat und Empfang von Echos, aber abhängig von der Anzahl der Verbindungen wird derselbe Client, der die Nachricht gesendet hat, basierend auf der Anzahl der verbundenen Clients zurückgemeldet. z. B. 3 Clients, mit denen client2 verbunden ist, sendet ein Ping-Echo zurück an den Client 2, 3 mal. Es sollte eine Schleife von IPEndPoint Liste aller verbundenen Benutzer durchlaufen und eine sock.SendTo (data, data.Length, Clients [i]);

aber das Echo zurück zu dem Client, der die Nachricht gesendet hat. keine Ahnung, was ich falsch gemacht habe, aber ich dachte, ich hätte alles richtig gemacht. aber das stört mich. Einige Hinweise auf das, was ich falsch gemacht habe, wären sehr willkommen.

private static void Main(string[] args) 
    { 
     //create a socket 
     //create a end point to listen on 
     //bind 
     //listen 
     //accept the socket on a new socket 
     //receive 
     //store the connection in a list 
     //ping back on their socket 
     //go back to listening state 

     Console.Title = " TCP NAT PT Server"; 

     StartServer(); 
    } 

    private static void StartServer() 
    { 
     Thread ListenThread = new Thread(new ThreadStart(Listen)); 
     ListenThread.Start(); 
     Console.WriteLine("ListenThread: " + ListenThread.ThreadState); 
    } 

    private static void Listen() 
    { 
     try 
     { 
      server.Bind(ep); 
      server.Listen(0); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.Message); 
     } 
     while (true) 
     { 
      try 
      { 
       Socket handler = server.Accept(); 

       Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCommunication)); 
       clientThread.Start((object)handler); 
       Console.WriteLine("ReceiveThread: " + clientThread.ThreadState); 

       string rstr = handler.RemoteEndPoint.ToString(); 
       string[] rdata = rstr.Split(':'); 

       IPEndPoint rep = new IPEndPoint(IPAddress.Parse(rdata[0]), int.Parse(rdata[1])); 
       clients.Add(rep); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
     } 
    } 

    private static void HandleClientCommunication(object Client) 
    { 
     Socket sock = (Socket)Client; 
     byte[] data = new byte[1024]; 
     string str = string.Empty; 

     while (true) 
     { 
      try 
      { 
       int rec = sock.Receive(data, SocketFlags.None); 
       Array.Resize(ref data, rec); 
       str = Encoding.ASCII.GetString(data); 
       Console.WriteLine(sock.RemoteEndPoint.ToString() + " >> " + str); 

       //Console.WriteLine(clients.Count); 
       //Console.WriteLine(clients[0].Address + ":" + clients[0].Port); 

       string temp = Encoding.ASCII.GetString(data); 
       temp = "Echo: " + temp; 
       data = Encoding.ASCII.GetBytes(temp); 
       Console.WriteLine("Data.Length: " + temp.Length); 

       for (int i = 0; i < clients.Count; i++) 
       { 
        sock.SendTo(data, data.Length, SocketFlags.None, clients[i]); 
        //sock.Send(data, data.Length, SocketFlags.None); 
       } 

       data = new byte[1024]; 
      } 
      catch (Exception e) 
      { 
       //socket error 
       Console.WriteLine(e.Message); 
      } 
     } 

Antwort

1

Das Problem ist in dieser Zeile:

sock.SendTo(data, data.Length, SocketFlags.None, clients[i]); 

nach SendTo method doc:

Wenn Sie ein verbindungsorientiertes Protokoll verwenden, müssen Sie zuerst stellen Sie eine Remote-Host-Verbindung durch Anrufen der Connect-Methode oder Annahme einer eingehenden Verbindungsanforderung mit der Accept-Methode

Sie verwenden einen Socket, der an Endpunkt A angeschlossen ist, um Bytes über TCP an Endpunkt B zu senden, was nicht funktionieren würde.

Statt Endpunkte in den Kunden zu halten, um eine Liste von Sockets in der hören Methode halten:

while (true) 
     { 
      try 
      { 
       Socket handler = server.Accept(); 

       Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCommunication)); 
       clientThread.Start((object)handler); 
       Console.WriteLine("ReceiveThread: " + clientThread.ThreadState); 

       clients.Add(handler); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
     } 

und die Schleife ändern, um Nachrichten an diese zu senden:

for (int i = 0; i < clients.Count; i++) 
{ 
    clients[i].Send(data); 
} 

Nur ein Heads up: Um Fehler zu vermeiden, müssen Sie Elemente aus der Clients Liste entfernen, sobald der Client-Socket in der Nähe kommt.

+1

lustig genug, ich tat genau das eine Stunde nach dem Legen im Bett zu denken, was ich falsch gemacht hatte, und habe es in etwa 30 Sekunden funktioniert. Danke auch für die Hilfe. zumindest werden andere in der Lage sein, etwas davon zu nutzen, ich würde abstimmen, aber ich bin nicht in der Lage zu sein =/ – Krazor

+0

Haha, passiert manchmal, vor allem, wenn Sie ins Bett gehen müssen :)) – akazemis