У меня есть сервер, который иногда не принимает новые подключения. Эта проблема возникает, когда я открываю несколько соединений 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");
}
}