namespace DHCPserver
{
/// <summary>
/// 客户端申请组件
/// </summary>
struct clientComputerInfo
{
private string computerMac; //暂时还不知道如何取MAC地址,先用这个吧
public string ComputerMac
{
get { return computerMac; }
set { computerMac = value; }
}
private string computerName;
public string ComputerName
{
get { return computerName; }
set { computerName = value; }
}
public clientComputerInfo(string computerName)
{
this.computerName = computerName;
this.computerMac = "00-00-00-00-00-00-00-E0";
}
public void showDhcpClientInfo()
{
Console.WriteLine("有一个DHCP客户端向你索要地址,它的信息如下");
Console.WriteLine("计算机名为:" + computerName);
Console.WriteLine("计算机mac地址:" + computerMac);
}
}
/// <summary>
/// 数据访问组件
/// </summary>
class sqlDataSourceAccess
{
//放心,实际开发中绝对不会把它硬编码在此,通过反编译可以反回这个.如果是在ASP.NET中的Web.Config中还可以通过命令行加密.aspnet_regiis -pef ...
private string sqlConnStr = "Data Source=HELLA-PC;Integrated Security=true;Initial Catalog=DHCPServerIPPool;";
private SqlConnection sqlConn = null;
private DataSet sqlDataSet = null;
private SqlCommand sqlCmd = null;
/// <summary>
/// 打开一个连接
/// </summary>
/// <returns>返回一个连接</returns>
public SqlConnection getSqlConn()
{
try
{
sqlConn = new SqlConnection(sqlConnStr);
sqlConn.Open();
return sqlConn;
}
catch (Exception)
{
throw new Exception("数据库连接发生要异常!");
}
}
/// <summary>
/// 关闭一个已打开的连接
/// </summary>
/// <param name="sqlConn">已打开的连接对象</param>
public void closeSqlConn(SqlConnection sqlConn)
{
if (sqlConn.State == ConnectionState.Open)
{
sqlConn.Close();
}
}
/// <summary>
/// 使用存过
/// </summary>
/// <param name="stor">存过名</param>
/// <param name="paras">存过参数</param>
/// <returns></returns>
public DataSet getDataSetSto(string stor, SqlParameter[] paras)
{
sqlCmd = new SqlCommand(stor, getSqlConn());
sqlCmd.CommandType = CommandType.StoredProcedure;
for (int i = 0; i < paras.Length; i++)
{
if (paras[i] != null)
{
sqlCmd.Parameters.Add(paras[i]);
}
}
using (SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlCmd))
{
sqlDataSet = new DataSet();
sqlAdapter.Fill(sqlDataSet);
return sqlDataSet;
}
}
/// <summary>
/// 返一个sql命令返回的结果集
/// </summary>
/// <param name="sql">sql命令</param>
/// <param name="paras">ql命令中的参数</param>
/// <returns>此sql命令的结果集</returns>
public DataSet getDataSet(string sql, SqlParameter[] paras)
{
sqlCmd = new SqlCommand(sql, getSqlConn());
for (int i = 0; i < paras.Length; i++)
{
if (paras[i] != null)
{
sqlCmd.Parameters.Add(paras[i]);
}
}
using (SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlCmd))
{
sqlDataSet = new DataSet();
sqlAdapter.Fill(sqlDataSet);
return sqlDataSet;
}
}
}
class LogInto
{
public void writeAssignIpInfo(clientComputerInfo AssignIpInfo, string assignIp)
{
if (!File.Exists(@"G:\Exception\AssignIpInfo.txt"))
{
StreamWriter sw = new StreamWriter(File.Create(@"G:\Exception\AssignIpInfo.txt"));
sw.WriteLine("时间为:" + DateTime.Now.ToString() + ":第一次分配IP为" + assignIp + " 分配给了mac为-->" + AssignIpInfo.ComputerMac + " 主机名为:" + AssignIpInfo.ComputerName);
sw.Flush();
sw.Close();
}
else
{
File.AppendAllText(@"G:\Exception\AssignIpInfo.txt", "时间为:" + DateTime.Now.ToString() + ":分配IP为" + assignIp + " 分配给了mac为-->" + AssignIpInfo.ComputerMac + " 主机名为:" + AssignIpInfo.ComputerName);
}
}
public void writerException(Exception ex)
{
if (!File.Exists(@"G:\Exception\exception.txt"))
{
StreamWriter sw = new StreamWriter(File.Create(@"G:\Exception\exception.txt"));
sw.WriteLine(DateTime.Now.ToString() + "这是第一次发生异常:" + ex.Message);
sw.Flush();
sw.Close();
}
else
{
File.AppendAllText(@"G:\Exception\exception.txt", DateTime.Now + "异常信息:" + ex.Message);
}
}
}
class Program
{
static sqlDataSourceAccess findIpObj = new sqlDataSourceAccess();
static LogInto logInto = new LogInto();
static List<TcpClient> dhcpClient = new List<TcpClient>();
static void Main(string[] args)
{
Console.BackgroundColor = ConsoleColor.Blue;
IPAddress ip = IPAddress.Parse("192.168.1.1"); //DHCP服务器地址
IPEndPoint ipAndEnd = new IPEndPoint(ip, 68);
TcpListener tcpListener = new TcpListener(ipAndEnd);
tcpListener.Start();
//起来无限监听的线程,该线程下还有两儿子线程
Thread listenerTh1 = new Thread(listenerClient);
listenerTh1.Start(tcpListener);
//再来一个广播线程
Thread broadCastTh = new Thread(new ThreadStart(broadCastClient));
broadCastTh.Start();
//再来服务器展示时间线程
Thread serverShowTime = new Thread(new ThreadStart(showTimeClient));
serverShowTime.Start();
}
/// <summary>
/// 一个时间展示的小线程
/// </summary>
static void showTimeClient()
{
while (true)
{
Console.Title = DateTime.Now.ToString();
Thread.Sleep(1000);
}
}
/// <summary>
/// 对每个向此服务器索引过ip的客户端广播信息。
/// </summary>
static void broadCastClient()
{
try
{
StreamWriter broadCast = null;
while (true)
{
Console.WriteLine("果断向客户端广播信息");
string broadCastMess = Console.ReadLine();
foreach (TcpClient temp in dhcpClient)
{
broadCast = new StreamWriter(temp.GetStream());
broadCast.WriteLine(broadCastMess);
broadCast.Flush();
}
}
}
catch (Exception ex) //使用老祖宗比较爽
{
logInto.writerException(ex);
}
}
static void listenerClient(object obj)
{
TcpListener tcpListener = obj as TcpListener;
TcpClient clientTcpclient = null;
while (true)
{
clientTcpclient = tcpListener.AcceptTcpClient();
dhcpClient.Add(clientTcpclient); //每来一个索取IP的客户加入此泛型集合
//来一个读线程,来说明有索取IP的客户向我们索要地址来了
Thread clientReader = new Thread(toClientReader);
clientReader.Start(clientTcpclient.GetStream());
//向客户的线程,为索取IP的客户展示选择.注意,此线程采有形式参数的委托类型
Thread clientWriter = new Thread(toClientWriter);
clientWriter.Start(clientTcpclient.GetStream());
}
}
/// <summary>
/// 输出申请IP客户端的详细信息
/// </summary>
/// <param name="obj">是委托ParameterizedThreadStart()中的Object参数,以便与此委托相匹配.</param>
private static void toClientReader(object obj)
{
NetworkStream nsC = obj as NetworkStream;
// 对网络络流进行一次包装,方便操作
StreamReader serverReader = new StreamReader(nsC);
StreamWriter serverWriter = new StreamWriter(nsC);
//输出索取IP客户的详细信息,待一下可以写日志
clientComputerInfo dhcpClient = new clientComputerInfo();
dhcpClient.ComputerMac = serverReader.ReadLine();
dhcpClient.ComputerName = serverReader.ReadLine();
dhcpClient.showDhcpClientInfo();
try
{
string optionIp = serverReader.ReadLine();
int option = Convert.ToInt32(optionIp);
if (option >= 1 && option <= 200)
{
Console.WriteLine("这是一个DHCP Offer包的过程"); //放心,这里以后会用UdpClient来改,引外,这里还要进行广播,因为毕竟这个DHCP与Linux中的DHCP工作原理有点不同.
SqlParameter para = new SqlParameter("@ID", SqlDbType.Int);
para.Value = option;
DataSet ipDataSet = findIpObj.getDataSetSto("selectIP", new SqlParameter[] { para });
serverWriter.WriteLine("好这个ip就分给你了!IP:-->" + ipDataSet.Tables[0].Rows[0][0].ToString() + "再见!"); //这里里在数据库中忘记了设置"子网"+"网关"+"Dns地址",记得加上.
serverWriter.Flush();
//进行分配后进行日志记录
logInto.writeAssignIpInfo(dhcpClient, ipDataSet.Tables[0].Rows[0][0].ToString());
}
else
{
serverWriter.WriteLine("你选择有误!");
serverWriter.Flush();
}
}
catch (Exception ex)
{
logInto.writerException(ex);
}
}
/// <summary>
/// 向客户端发放还没有用的IP
/// </summary>
/// <param name="obj">是委托ParameterizedThreadStart()中的Object参数,以便与此委托相匹配.</param>
private static void toClientWriter(object obj)
{
NetworkStream nsC = obj as NetworkStream;
StreamWriter serverWriter = new StreamWriter(nsC);
DataSet selectDataSet = findIpObj.getDataSet("SELECT ID,IP FROM DHCPIpPool WHERE IPStatus=0", new SqlParameter[0]);
string sendLine = string.Empty;
for (int i = 0; i < selectDataSet.Tables.Count; i++) //有多少个表
{
for (int j = 0; j < selectDataSet.Tables[i].Rows.Count; j++) //每个表有多少行
{
for (int z = 0; z < selectDataSet.Tables[i].Columns.Count; z++) //每个有多少列
{
sendLine += selectDataSet.Tables[i].Rows[j][z].ToString() + " ";
}
serverWriter.WriteLine(sendLine.ToString());
serverWriter.Flush();
sendLine = "";
Thread.Sleep(1);
}
}
serverWriter.WriteLine("请选择一个IP的编号:");
serverWriter.Flush();
}
}
}
/*
CREATE PROC selectIP
@ID INT
AS
SELECT IP FROM DHCPIpPool WHERE ID=@ID AND IPStatus=0
UPDATE DHCPIpPool SET IPStatus=1 WHERE ID=@ID
*/
namespace client
{
struct clientComputerInfo
{
private string computerMac; //暂时还不知道如何取MAC地址,先用这个吧
public string ComputerMac
{
get { return computerMac; }
set { computerMac = value; }
}
private string computerName;
public string ComputerName
{
get { return computerName; }
set { computerName = value; }
}
public clientComputerInfo(string computerName)
{
this.computerName = computerName;
this.computerMac = "00-00-00-00-00-00-00-E0";
}
public void showDhcpClientInfo()
{
Console.WriteLine("有一个DHCP客户端向你索要地址");
Console.WriteLine("计算机名为:" + computerName);
Console.WriteLine("计算机mac地址:" + computerMac);
}
}
class Program
{
static void Main(string[] args)
{
Console.BackgroundColor = ConsoleColor.Red;
IPAddress ip = IPAddress.Parse("192.168.1.1"); //原本是要"源:0.0.0.0 目:255.255.255.255 端:67",而且使用的UDP端口,现在是使用TcpClient模拟
IPEndPoint ipAndEnd = new IPEndPoint(ip, 68);
TcpClient clientConnection = new TcpClient();
clientConnection.Connect(ipAndEnd);
Console.WriteLine("连接DHCP服务器成功!");
StreamReader clientReader = new StreamReader(clientConnection.GetStream());
StreamWriter clientWriter = new StreamWriter(clientConnection.GetStream());
//向服务器申请,关于自己机器的详细信息,很快走完.
Thread sendServerInfoTh = new Thread(new ParameterizedThreadStart(sendServerInfo));
sendServerInfoTh.Start(clientWriter);
//取得服务器的IP选择列表
Thread getServerIpList = new Thread(new ParameterizedThreadStart(getServerIpListClient));
getServerIpList.Start(clientReader);
clientWriter.WriteLine(Console .ReadLine());
clientWriter.Flush();
Console.WriteLine("正在等待服务器发放ip,请稍候..");
Thread.Sleep(2000);
string assIp = clientReader.ReadLine();
Console.WriteLine(assIp);
}
//使用有参数的委托,也就是使用" public delegate void ParameterizedThreadStart(object obj);"这个委托
private static void sendServerInfo(object obj)
{
StreamWriter clientWriter = obj as StreamWriter; //进行一次类型转换,因为ParameterizedThreadStart的参数是object,是老祖宗
Console.WriteLine("正向它发送DHCP Discover包!...");
clientComputerInfo DHCPDiscover = new clientComputerInfo(Dns.GetHostName());
clientWriter.WriteLine(DHCPDiscover.ComputerMac); //发送客户端的mac
clientWriter.WriteLine(DHCPDiscover.ComputerName);
clientWriter.Flush();
Console.WriteLine("我已经发送完向DHCP服务器索要IP等信息的关于自己的信息");
}
/// <summary>
/// 读取服务器中可用的IP选择列表,还方便进行接收服务器广播
/// </summary>
/// <param name="obj"> public delegate void ParameterizedThreadStart(object obj);</param>
private static void getServerIpListClient(object obj)
{
StreamReader clientReader = obj as StreamReader;
while (true)
{
Console.WriteLine(clientReader.ReadLine());
}
}
}
}