【问题标题】:Instead of scanning multiple ports I'm scanning only one and when port is closed my app closes而不是扫描多个端口,我只扫描一个端口,当端口关闭时,我的应用程序关闭
【发布时间】:2012-01-27 02:44:09
【问题描述】:

我正在尝试使用异步扫描一次扫描多个端口。问题是我只能显示第一个工作端口,然后等待我的应用程序关闭 20 秒,却没有告诉我端口已关闭。

这段代码有什么问题?

private void btnStart_Click(object sender, EventArgs e)
{
    for (int port = 80; port < 100; port++)
    {
        ScanPort(port);
    }
}

private void ScanPort(int port)
{
    var client = new TcpClient();

    try 
    {
        client.BeginConnect(IPAddress.Parse("74.125.226.84"), port, new AsyncCallback(CallBack), client);
    } 
    catch (SocketException) 
    {
        client.Close();
    }
}

private void CallBack(IAsyncResult result)
{
    var client = (TcpClient)result.AsyncState;

    client.EndConnect(result);

    if (client.Connected)
    {
        this.Invoke((MethodInvoker)delegate
        {
            txtDisplay.Text += "open2" + Environment.NewLine;
        });
    }
    else
    {
        this.Invoke((MethodInvoker)delegate
        {
            txtDisplay.Text += "closed2" + Environment.NewLine;
        });
    }
}

【问题讨论】:

  • 你说你的应用程序正在关闭是什么意思?另外,你到底得到了什么输出?
  • @Scott Smith,是的,只是关闭没有错误,没有警告。输出是open,因为我知道我开始使用的端口(80)是打开的。
  • 您需要使用 try catch 将代码包装在 CallBack 函数中并处理 SocketExceptions。由于端口未打开,后续连接很可能被拒绝。这发生在 EndConnect 调用中。
  • @Scott Smith,这修复了意外关闭,但我仍然无法仅检查第一个端口。
  • 您的代码正在检查所有端口。我自己对此进行了测试,并且端点没有在除 80 之外的其他端口上侦听,因此连接被拒绝。

标签: c# winforms tcpclient asynccallback


【解决方案1】:

在您的回调方法中,我会确保关闭连接并处理 TcpClient。 TcpClient.EndConnect(IAsyncResult) 也可以抛出异常。我也看不到在哪里捕获端口号以显示给用户。我会写这样的回调。

编辑:我实际上并没有编译或执行我的代码(抱歉)。我还发现了另一篇文章,它展示了如何在 C# 中创建端口扫描器,http://www.dijksterhuis.org/building-a-simple-portscanner-in-c/ 在这篇文章中有一条评论指出,

这里有个问题:TCPClient.Close() 函数的 .NET 实现实际上并没有正确关闭连接。所以我们需要在调用 TCPClient.Close 之前执行额外的步骤来获取表示连接的流并关闭它。

private void CallBack(IAsyncResult result) 
{ 
    var client = (TcpClient)result.AsyncState; 
    bool connected = false;

    try
    {
        client.EndConnect(result);
        connected = client.Connected;
    }
    catch (SocketException)
    {
    }
    catch (ObjectDisposedException)
    {
    }
    finally
    {
        if (client.Connected)
        {
            client.Close();
        }

        client.Dispose();
    }

    if (connected) 
    { 
        this.Invoke((MethodInvoker)delegate 
        { 
            txtDisplay.Text += "open2" + Environment.NewLine; 
        }); 
    } 
    else 
    { 
        this.Invoke((MethodInvoker)delegate 
        { 
            txtDisplay.Text += "closed2" + Environment.NewLine; 
        }); 
    } 
} 

【讨论】:

  • 好的,我复制并粘贴了您的代码只是为了看看它是否有效。出现第一个无法访问的错误:client.Dispose();应有的保护水平。让我看看没有它会发生什么。
  • 首先,代码输出看起来是正确的。 80 端口打开,其余端口关闭。但后来我改变了从端口 79 开始,我知道它是关闭的,输出状态它是打开的,并没有显示端口 80 是打开的,其余的都是关闭的。
  • @NewHelpNeeder 您的评估不正确。您看到的那个说它是开放的,是 80。您正在执行异步代码,所以您会立即看到 80,并且需要 20 秒才能看到包括 79 在内的其他输出。
  • @Scott Smith,我在 for 循环中将行更改为:int port = 79; port &lt; 100; port++ 所以首先我应该看到关闭然后打开然后休息关闭,对吗?我看到先开,后关。
  • 哦,我明白了,因为端口 80 已关闭并且它是异步的,所以我看到 80 端口打开并关闭,因为它们的状态检查速度较慢。好的,我明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多