远程登录阻止C#TCP服务器 [英] Telnet Blocking C# TCP Server

查看:394
本文介绍了远程登录阻止C#TCP服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写在C#中的TCP服务器,并遇到了一个奇怪的和潜在的安全性问题,以及。

I am writing a TCP server in C#, and have run into a strange and potentially a security issue as well.

我接受新的连接基本牌坊如下:

My basic arch for accepting new connections is as follows:


  1. AC#插座端口上监听,使用 AcceptAsync方法的方法来接受传入的连接。

  2. 分拆使用线程池为完成接受。

  1. A C# Socket listening on a port, using the AcceptAsync method to accept incoming connections.
  2. Spinning off accepted connections using the ThreadPool for finishing the accept.

一切都工作的很好,但是一切都研磨到,如果停止某人远程登录到该端口。

Everything works quite well, however everything grinds to a halt if someone telnets into the port.

症状:


  • 如果我远程登录到我的服务器,并做不发送任何数据(即不打任何键),服务器永远不会完成接受连接。

  • If I telnet into my server and do not send any data (i.e. do not hit any keys) the server will never finish accepting the connection.

我的 SocketAsyncEventArgs.Completed 回调从不打的telnet连接。

My SocketAsyncEventArgs.Completed callback is never hit for the telnet connection.

更糟糕的是,所有进一步的连接被阻塞/排队,千万不要被我的代码接受。它们被放入 CLOSE_WAIT 状态:

Even worse, all further connections are blocked/queued and never get accepted by my code. They are put into a CLOSE_WAIT state:

TCP 127.0.0.1:8221机会: 53960 CLOSE_WAIT

TCP 127.0.0.1:8221机会:53962 CLOSE_WAIT

TCP 127.0.0.1:8221机会:53964 CLOSE_WAIT

任何意见,将不胜感激。

Any advice would be appreciated.

StartAccept:

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

完成接受:

private void FinishAccept(object StateObject)
{
    SocketAsyncEventArgs args = (SocketAsyncEventArgs)StateObject;
    FinishAcceptInternal(args);
}

下面是连接的telnet Wireshark的,但发送数据之前:

Here is the wireshark from connecting telnet but before sending data:

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

这应该是完整的握手建立我的连接,但已完成事件从未提出。

This should be the complete handshake to establish my connection, but the Completed event is never raised.

推荐答案

回答我的问题,因为我找到了根本原因:

Answering my own question, as I found the underlying cause:

该错误是这一行:

if (AcceptArgs.Buffer == null ||
    AcceptArgs.Buffer.Length < 1024)
{
    AcceptArgs.SetBuffer(new byte[1024], 0, 1024);
}

这是因为如果你设置一个缓冲区,AcceptAsync方法将阻塞,直到它收到一些数据。

This is because if you set a buffer, AcceptAsync will block until it receives some data.

从的 MSDN

所需的最小缓冲区大小为288字节。如果指定了较大的缓冲区大小,则套接字将预计比在Winsock的AcceptEx调用接收的地址数据的一些额外的数据等,并会等到收到此额外的数据。

The minimum buffer size required is 288 bytes. If a larger buffer size is specified, then the Socket will expect some extra data other than the address data received by the Winsock AcceptEx call and will wait until this extra data is received.

我纠正代码:

// We set a null buffer here.
// If we set a valid buffer, the accept will expect data
// and will hang unless it gets it.
AcceptArgs.SetBuffer(null, 0, 0);



我不知道这是否是准确的正确的修复,设置288个字节或更小的缓冲区似乎没有解决问题。只有设置缓冲区为空造成不发送数据连接时要提出的已完成事件。

这篇关于远程登录阻止C#TCP服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆