2016-06-25 2 views
1

Я работал над настройкой TCP NAT Punch через сервер/клиентскую комнату. я успешно установил его в UDP, и теперь я хочу сделать то же самое для TCP, так как я немного груб на своих сокетах atm.Multi Threaded TCP Server Echo для всех клиентов

В любом случае клиенты могут подключаться нормально, общаться и получать эхо, но в зависимости от количества подключений он будет откликнуться на того же клиента, который отправил сообщение на основе количества подключенных клиентов. например, 3 клиента, conencted client2, отправляют ping его echos обратно клиенту 2, 3 раза. он должен проходить через список IPEndPoint всех подключенных пользователей и делать sock.SendTo (data, data.Length, клиенты [i]);

, но его повторение назад к клиенту, который отправил сообщение. не знаю, что я сделал неправильно, но я думал, что сделал все правильно. но это беспокоит меня. некоторые рекомендации относительно того, что я сделал неправильно, будут высоко оценены.

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); 
      } 
     } 

ответ

1

Проблема заключается в этой строке:

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

в соответствии с SendTo method doc:

Если вы используете протокол, ориентированный на соединение, вы должны сначала установить соединение удаленного хоста путем вызова метода Connect или принять запрос на входящий запрос с использованием метода Accept

Вы используете сокет, подключенный к конечной точке A, для отправки байтов в конечную точку B через TCP, которые не будут работать на самом деле.

Так вместо того, чтобы конечные точки в клиентах, хранить список сокетов в методе слушает:

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); 
      } 
     } 

и изменить цикл для отправки сообщений в этом:

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

Just A головы Чтобы избежать ошибок, вам нужно удалить элементы из клиентов после того, как клиентский сокет приблизится.

+1

достаточно смешно, я сделал именно то, что через час после укладки в постель, подумав, что я сделал не так, и заставил его работать примерно через 30 секунд. спасибо за помощь. по крайней мере, другие смогут получить от этого какую-то пользу, я бы голосовал, но я не могу =/ – Krazor

+0

Ха-ха, бывает иногда, особенно когда вам нужно ложиться спать :)) – akazemis