Сервер C # не принимает новые подключения - PullRequest
0 голосов
/ 01 ноября 2019

У меня есть сервер, который иногда не принимает новые подключения. Эта проблема возникает, когда я открываю несколько соединений TCP, но не всегда.

Сервер развернут в нескольких удаленных местах (облаке) для тестирования под разными RTT. Когда я открываю одно TCP-соединение, все работает, как и ожидалось, но когда я пробую 2 или более TCP-соединения от одного и того же клиента к серверу (на разных портах), соединение не устанавливается.

В частности, я проверилдо 5 соединений TCP локально и путем развертывания сервера в облаке (с RTT <5 мс) и работает, но когда сервер расположен на сервере с RTT> 75 мс, соединение по второму порту в большинстве случаев (~ 90%) не принимается.

Я считаю, что это связано с высоким RTT, учитывая, что это единственное различие между двумя местоположениями. Как только я установил режим блокировки на true, он работает, но я вижу, что это значительно снижает производительность приложения (из-за блокировки).

Это код:

List<Socket> _socket = new List<Socket>();
List<int> _Ports = new List<int> (3) { 48005, 48006, 48007 };

void FunServer ()
{
     for (int ii = 0; ii < _Ports.Count; ii++)
     {
         _socket .Add(new Socket(SocketType.Stream, ProtocolType.Tcp));
         _socket [ii].Blocking = false;
         IPEndPoint _endPoint = new IPEndPoint(IPAddress.Any, _Ports [ii]);
         _socket[ii].Listen(10);
         _socket [ii].Bind(_endPoint);
     }
     Thread _listeningThread = new Thread(this.ListeningFun);
     _listeningThread.IsBackground = true;
     _listeningThread.Start();
}

void ListeningFun()
{
     while (true)
     {
         for (int ii = 0; ii < _Ports.Count; ii++)
         {
             Socket _newClient = null;
             try
             {
                  _newClient = oServerSocket[ii].Accept();
             }                        
             catch (SocketException e)
             {
                  if (e.SocketErrorCode != SocketError.WouldBlock)
                  {
                       \\it never enters here
                  }
                  else
                  {
                       break; // when fails this the error received is: A non-blocking socket operation could not be completed immediately
                  }
             }
             // some other code here ...
         }
         Thread.Sleep(10);
     }
}

Если я установлю режим блокировки на true, он будет работать, но производительность для приложения будет ниже.

Мой вопрос такой: поскольку я проверяю каждые 10 мс, почему не могу прочитать во второй раз (илитретий и т. д.)?

У меня Wireshark работает на обеих машинах, и я вижу, что пакеты прибывают на оба порта целыми и невредимыми.

Как мне поступить с этим? Должен ли я использовать асинхронные операции?

РЕДАКТИРОВАТЬ:

Вот как я изменил код на основе прослушивателя Async (msdn и следующие https://social.msdn.microsoft.com/Forums/en-US/f3151296-8064-4358-98a3-7ecf3d2c474b/multiple-ports-listening-on-c?forum=ncl) и работалдля меня:

List<Socket> SocketList = new List<Socket>();
List<int> PortList = new List<int> (3) { 48005, 48006, 48007 };

public class State
{
    public int index = 0;
    public int port;
}

void FunServer ()
{
     for (int ii = 0; ii < PortList.Count; ii++)
     {
          Socket _s = new Socket(SocketType.Stream, ProtocolType.Tcp);
          _s.Blocking = false;
          IPEndPoint _endPoint = new IPEndPoint(IPAddress.Any, PortList[ii]);
          try
          {
              _s.Bind(endPoint); //Associates socket with a local endpoint
              _s.Listen(10);
              State _state = new State();
              _state.index = ii;
              _state.port = PortList[ii];  
              Console.WriteLine("Waiting for a connection...");
              _s.BeginAccept(new AsyncCallback(ListeningFun), _state);
              SocketList.Add(_s);
          }
          catch(Exception e)
          {
          }
     }
}

void ListeningFun(IAsyncResult ar)
{
     var _state = ar.AsyncState as State;
     var _port = state.port;

     try
     {
         Socket _s = SocketList[state.index].EndAccept(ar);
         // some more code here with the _s socket...
     }
     catch (ObjectDisposedException)
     {
         System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
     }
}


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...