Я пишу TCP-сервер на C # и столкнулся со странной и, возможно, проблемой безопасности.
Моя основная арка для приема новых соединений выглядит следующим образом:
- AC # прослушивание сокета через порт с использованием метода
AcceptAsync
для приема входящих соединений. - Отключение принятых соединений с использованием
ThreadPool
для завершения приема.
Все работает довольно хорошо, однако все останавливается, если кто-то подключается к порту.
Симптомы:
Если я telnet на свой сервер и не отправляю никаких данных (т.е. не нажимаю какие-либо ключи), сервер никогда не завершит прием соединения.
Мой SocketAsyncEventArgs.Completed
обратный вызов никогда не срабатывает для соединения через telnet.
Еще хуже, все дальнейшие соединения блокируются / ставятся в очередь и никогда не получатпринят по моему коду.Они переводятся в состояние CLOSE_WAIT
:
TCP 127.0.0.1:8221 chance:53960 CLOSE_WAIT
TCP 127.0.0.1:8221 chance:53962 CLOSE_WAIT
TCP 127.0.0.1:8221 chance:53964 CLOSE_WAIT
Любойсовет был бы оценен.
StartAccept:
private void StartAccept(SocketAsyncEventArgs AcceptArgs)
{
CurrentAcceptArgs = AcceptArgs;
AcceptArgs.AcceptSocket = null;
if (AcceptArgs.Buffer == null ||
AcceptArgs.Buffer.Length < 1024)
{
AcceptArgs.SetBuffer(new byte[1024], 0, 1024);
}
if (MainSocket != null)
{
lock (MainSocket)
{
// If this is false, we have an accept waiting right now, otherwise it will complete aynsc
if (MainSocket.AcceptAsync(AcceptArgs) == false)
{
ThreadPool.QueueUserWorkItem(FinishAccept, AcceptArgs);
StartAccept(GetConnection());
}
}
}
}
Завершенный обратный вызов для приема соединений:
protected override void OnIOCompleted(object sender, SocketAsyncEventArgs e)
{
PWClientRemote RemoteClient = e.UserToken as PWClientRemote;
// Determine which type of operation just completed and call the associated handler.
switch (e.LastOperation)
{
case SocketAsyncOperation.Accept:
StartAccept(GetConnection());
ThreadPool.QueueUserWorkItem(FinishAccept, e);
break;
default:
base.OnIOCompleted(sender, e);
break;
}
}
Finish Accept:
private void FinishAccept(object StateObject)
{
SocketAsyncEventArgs args = (SocketAsyncEventArgs)StateObject;
FinishAcceptInternal(args);
}
Вот проводник от соединенияtelnet, но перед отправкой данных:
No. Time Source Destination Protocol Length Info
1 0.000000 192.168.1.146 192.168.1.109 TCP 66 59766 > 8221 [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
2 0.000076 192.168.1.109 192.168.1.146 TCP 66 8221 > 59766 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
3 0.000389 192.168.1.146 192.168.1.109 TCP 60 59766 > 8221 [ACK] Seq=1 Ack=1 Win=65536 Len=0
Это должно быть полное рукопожатие для установления моего соединения, но событие Completed
никогда не возникает.