程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 動態取得本機可用的端口

動態取得本機可用的端口

編輯:關於.NET

今天在項目中考慮這樣一件事情:我需要動態實例化一個服務,監聽某個端 口。那麼該怎麼來實現這個需求呢?

我立馬想到是否有這樣的函數,例 如GetAvaliablePorts呢?主意不錯,但確沒有找到。原先Win32 API中有一個函 數(EnumPorts),但import來過來之後也沒有用。

此路不通,看來要自己 動手了。再大的困難也嚇不倒英雄的中華兒女嘛。

首先,要知道一些有 關端口號的基礎知識

所有的端口都應該大於0,而且小於65535

微 軟建議,1024及以前的端口號保留給系統用。也就是說,我們自己程序監聽的端 口最好是大於1024

其次,因為沒有內置的方法來測試某個端口是否可用 ,我們可能需要自己編寫方法來做這個事情。那麼怎麼做呢?我想到,可以用 socket來測試。我編寫了如下這樣一個函數

///  <summary>
/// 這個方法是驗證某個端口是否可用
///  </summary>
/// <param name="port"></param>
/// <returns></returns>
static bool IsAvaliable (int port)
{
    Socket sk = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
    bool result = false;
    try
     {

sk.Bind(new IPEndPoint(IPAddress.Any, port));//嘗試綁定 ,因為如果該端口已經被使用,則無法綁定,會導致異常

         result = true;
    }
    catch
     {
        result = false;
    }
     finally
    {
        sk.Close();
     }
    return result;
}

然後,我就可以 在代碼中這樣使用

static void Main(string[] args)
{
    Console.WriteLine(IsAvaliable(8080));//如果8080端口可用 ,則返回true,反之,返回false
    Console.Read();
}

最後,我還可以編寫另外一個方法,得到一個可用的端口

/// <summary>
/// 這個方法取得一個可用的端口
/// </summary>
///  <returns></returns>
static int GetAvaliablePort()
{
    Random rnd = new Random();
    int  port = rnd.Next(1024, 65535);//隨機產生一個動態的端口號
     while (!IsAvaliable(port))
    {
        port  = rnd.Next(1024, 65535);
    }
    return  port;
} 

在調用程序中,就可以這樣來調用它

Console.WriteLine(GetAvaliablePort());

看起 來不錯,對吧?但是如果我們要一次性得到10個不同的可用端口號呢?我們會大 致下面這樣寫代碼

for (int i = 0; i < 10; i++)
{
    Console.WriteLine(GetAvaliablePort());
} 

但是,讓人吃驚的是,我們看到下面這樣的輸出結果。

這是如何解釋呢?為什麼既然是隨機數,又仍然是重復呢?

這是因為 我們的10次循環之間幾乎沒有間隔(特別是我的機器配置又很好的情況下),所 以,對於隨機數的產生器,它實際上無法進行區分。我自己感覺就是,如果兩個 操作之間幾乎沒有時間間隔,那麼隨機數也是一樣的。

那麼該如何解決 該問題?好吧,我們可以刻意地讓每次循環有一些間隔

for (int  i = 0; i < 10; i++)
{
    Thread.Sleep (100);//我們強制讓進程休眠0.1秒
    Console.WriteLine (GetAvaliablePort());
} 

這樣大家總該是沒有意見了吧?

最後,我們對代碼進行一些重構,封 裝之後的完整代碼如下

using System;
using  System.Collections.Generic;
using System.Text;
using  System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace  ConsoleApplication1
{
    class Program
     {
        static void Main(string[] args)
         {
            PortHelper helper = new  PortHelper();
            Console.WriteLine("當前8080 端口是否可用?"+helper.IsAvaliable(8080));
             Console.WriteLine("取得10個可用的端口:");
             for (int i = 0; i < 10; i++)
             {
                Thread.Sleep(100);
                 Console.WriteLine (helper.GetAvaliablePort());
            }
             Console.Read();
        }
     }
        public class PortHelper
         {
            /// <summary>
             /// 這個方法是驗證某個端口是否可用
             /// </summary>
            ///  <param name="port"></param>
             /// <returns></returns>
             public bool IsAvaliable(int port)
            {
                Socket sk = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                bool result = false;
                 try
                 {
                    sk.Bind(new  IPEndPoint(IPAddress.Any, port));//嘗試綁定,因為如果該端口已經被使用 ,則無法綁定,會導致異常
                     result = true;
                }
                 catch
                 {
                    result = false;
                }
                 finally
                {
                     sk.Close();
                 }
                return result;
             }
            ///  <summary>
            /// 這個方法取得一個可用 的端口
            /// </summary>
             /// <returns></returns>
             public int GetAvaliablePort()
             {
                Random rnd = new  Random();
                int port = rnd.Next (1024, 65535);//隨機產生一個動態的端口號
                 while (!IsAvaliable(port))
                 {
                    port =  rnd.Next(1024, 65535);
                }
                 return port;
             }
        }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved