用c#编写一个dhcp服务

用c#编写一个dhcp服务

用c#编写一个dhcp服务

一、DHCP是什么?

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)通常被应用在大型的局域网络环境中,主要作用是集中的管理、分配IP地址,使网络环境中的主机动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。

说白了,每台网络设备想要上网必须要有ip地址,但是现在的互联网ip4地址资源有限,无法让这么多的设备没人一个互联网地址,于是路由器就出现了,路由器的作用就是将局域网的数据包转发到广域网上,使局域网内机器也能访问互联网,局域网可使用的网段(私网地址段)有三大段:

10.0.0.0~10.255.255.255(A类)

172.16.0.0~172.31.255.255(B类)

192.168.0.0~192.168.255.255(C类)

机器地址的获取可以通过dhcp进行分配,以免出现同一个地址被多台设备使用的情况

用c#编写一个dhcp服务

那么今天我们来用c#实现一个小型的dhcp服务器

二、c#编写dhcp

用c#编写一个dhcp服务

客户机与dhcp服务器之间的报文交换可以看上图

1、客户机发送dhcp discovery报文

2、dhcp接收到报文后发送dhcp offer报文

3、客户机收到后发送请求报文

4、dhcp发送确认报文(包含分配的ip地址)

5、客户机如果释放ip地址也会发送一个释放报文给dhcp

dhcp默认使用UDP进行报文传输,报文的格式如下

用c#编写一个dhcp服务

下面我来用c#编写一个dhcp服务器

原理很简单,就是创建一个UDPclient,监听67,68端口,进行报文的发送与接收

#region Copyright Information
/*
 * (C)  2005-2007, Marcello Cauchi Savona
 *
 * For terms and usage, please see the LICENSE file
 * provided alongwith or contact marcello_c@hotmail.com
 * http://www.cheekyneedle.com
 * 
 * 
 */
#endregion


/*
 * clsUDP
 * shall start a listner, and raise an event every time data arrives on a port
 * shall also be able to send data via udp protocol
 * .Dispose shall remove all resources associated with the class
 */


using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using Microsoft.Win32;


namespace SmallDHCPServer_C
{
   class clsUDP

    {
        #region "Class Variables"
            private Int32 PortToListenTo, PortToSendTo = 0;
            private string rcvCardIP;
            public bool IsListening;
            // call backs for send/recieve!
            public UdpState s;
        #endregion

        #region "Class Events"
            public delegate void DataRcvdEventHandler(byte[] DData, IPEndPoint RIpEndPoint);
            public event DataRcvdEventHandler DataRcvd;
            public delegate void ErrEventHandler(string Msg);
        #endregion

            //class constructors
        public clsUDP()
        {
            IsListening = false;
        }
        //overrides pass the port to listen to/sendto and startup
        public clsUDP(Int32 PortToListenTo,Int32 PortToSendTo, string rcvCardIP) 
        {
            try
            {
                IsListening = false;
                this.PortToListenTo = PortToListenTo;
                this.PortToSendTo = PortToSendTo;
                this.rcvCardIP = rcvCardIP;
                StartListener();
            }
            catch(Exception ex) 
            {
               Console.WriteLine (ex.Message);
               
            }
        }

        //string property to contain the class name
        private string ClassName
        {
            get {return "clsUDP";
            }
        }

        //function to send data as a byte stream to a remote socket
       // modified to work as a callback rather than a block
        public void SendData(byte[] Data)
        {

            try
            {
                s.u.BeginSend(Data, Data.Length, "255.255.255.255", PortToSendTo, new AsyncCallback(OnDataSent), s);
                //s.u.Send(Data, Data.Length, "255.255.255.255", PortToSendTo);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        // This is the call back function, which will be invoked when a client is connected
        public void OnDataSent(IAsyncResult asyn)
        {

            try
            {
                //get the data
                UdpClient ii = (UdpClient)asyn;
                ii.EndSend(asyn); // stop the send call back
            }
            catch (Exception ex)
            {
                if (IsListening == true)
                    Console.WriteLine(ex.Message);
            }
        }



       //function to start the listener call back everytime something is recieved
        private void IniListnerCallBack()
        {
            try
            {
               // start teh recieve call back method
                s.u.BeginReceive(new AsyncCallback(OnDataRecieved), s);
            }
            catch (Exception ex)
            {
                if (IsListening == true)
                    Console.WriteLine(ex.Message);
            }
        }


        // This is the call back function, which will be invoked when a client is connected
       public void OnDataRecieved(IAsyncResult asyn)
       {
           Byte[] receiveBytes;
           UdpClient u;
           IPEndPoint e;

           try
           {

               u = (UdpClient)((UdpState)(asyn.AsyncState)).u;
               e = (IPEndPoint)((UdpState)(asyn.AsyncState)).e;

               receiveBytes = u.EndReceive(asyn, ref e);
               //raise the event with the data recieved
               DataRcvd(receiveBytes, e);
            }
           catch (Exception ex)
           {
               if (IsListening == true)
                   Console.WriteLine(ex.Message);
           }
           finally
           {
               u = null;
               e = null;
               receiveBytes = null;
               // recall the call back
               IniListnerCallBack();
           }
          
       }
           
       



        //function to start the listener 
        //if the the listner is active, destroy it and restart
        // shall mark the flag that the listner is active
        private void StartListener()
        {
           // byte[] receiveBytes; // array of bytes where we shall store the data recieved
            IPAddress ipAddress;
            IPEndPoint ipLocalEndPoint;


            try
            {

                IsListening = false;
                //resolve the net card ip address
                ipAddress = IPAddress.Parse(rcvCardIP);
                //get the ipEndPoint
                ipLocalEndPoint = new IPEndPoint(ipAddress, PortToListenTo);
                // if the udpclient interface is active destroy
                if (s.u != null) s.u.Close();
                s.u = null; s.e = null;
                //re initialise the udp client
                             
                s = new UdpState();
                s.e = ipLocalEndPoint;
                s.u = new UdpClient(ipLocalEndPoint);
               
                IsListening = true; // set to start listening
                // wait for data
                IniListnerCallBack();        
            }
            catch (Exception ex)
            {
                if (IsListening == true)
                    Console.WriteLine(ex.Message);
            }
            finally
            {
                 if (s.u == null) {
                    Thread.Sleep(1000);
                    StartListener(); }
                 else {
                    ipAddress = null;
                    ipLocalEndPoint = null; }
            }
        }



        //stop the listener thread
        public void StopListener()
        {
            try
            {
                IsListening = false;
                if (s.u != null) s.u.Close();
                s.u = null; s.e = null;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        //dispose of all resources
        ~clsUDP()
        {
            try
            {
                StopListener();
                if (s.u != null) s.u.Close();
                s.u = null; s.e = null;
                rcvCardIP = null;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

       //class that shall hold the reference of the call backs
       public struct UdpState
       {
           public IPEndPoint e; //define an end point
           public UdpClient u; //define a client
      }


    }
}

完整的项目示例可以下载

一、源码下载

用c#编写一个dhcp服务

SmallDHCPServer_CodeProject.zip

{{collectdata}}

网友评论0