class PingExam

{
    public static void Main()
    {
        Ping ping = new Ping();
        string ip = "192.168.1.43"; // 目标ip
        int[] ports = { 20, 21, 25, 80, 8080, 2588 }; // 需要扫描的端口
        scanPort(IPAddress.Parse(ip), ports);
    }
    private static void scanPort(IPAddress address, int startPort, int endPort)
    {
        int[] ports = new int[endPort - startPort + 1];
        for (int i = 0; i < endPort-startPort+1; i++) {
            ports[i] = startPort + i;
        }
        scanPort(address, ports);
    }
    private static void scanPort(IPAddress address, int[] ports)
    {
        try {
            int count = ports.Length;
            AutoResetEvent[] arEvents = new AutoResetEvent[count]; // 同步对象
            for (int i = 0; i < count; i++) {
                arEvents[i] = new AutoResetEvent(false); // 同步对象, 初始未触发
                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.Bind(new IPEndPoint(IPAddress.Any, 0));
                socket.BeginConnect(new IPEndPoint(address, ports[i]), 
                    callback, 
                    new ArrayList() { socket, ports[i], arEvents[i]} // 传递3个参数: 当前socket, 端口, 同步对象
                    );
            }

            WaitHandle.WaitAll(arEvents); // 等待所有扫描工作完成
        }
        catch (Exception ex) {
            Console.WriteLine(ex.Message);
        }
    }

    private static void callback(IAsyncResult ar) // 扫描完成后的回调方法
    {
        ArrayList list = (ArrayList)ar.AsyncState; // 获取传递的参数
        Socket socket = (Socket)list[0];
        int port = (int)list[1];
        AutoResetEvent arevent = (AutoResetEvent)list[2];

        if (ar.IsCompleted && socket.Connected) {
            Console.WriteLine("port: {0} open.", port); // 检查 connected属性, 如果为true 则表示是开放的
        }
        else {
            Console.WriteLine("port: {0} closed.", port);
        }
        try {
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
        }
        catch {
        }
        arevent.Set(); // 完成后触发
    }
}