实习第12天 多线程监控网络软件,解析XML
关于微软的产品,可前往msdn论坛找答案
https://social.msdn.microsoft.com/Forums/zh-CN/home
利用winform,C#做了监控网络软件用到了网络、多线程、XML的知识,
检测所给的ip地址,连接是否正常,不正常的写入数据库日志文件,
ip数据利用xml存储可以动态配置。
C#中WinForm程序退出方法技巧总结 http://www.jb51.net/article/58816.htm
强制退出WinForm程序之Application.Exit和Environment.Eixt
错误:在VS上点击停止调试后,系统蓝屏了。
原因:VS上的停止调试,应该相当于任务管理系统的强制关闭作用,
在我多线程任务中读取或修改资源的时候被强制关闭,引发内存出错,
而电脑重启后线程操作的写入文件数据出现了一大堆奇怪的符号
解决方案:
我们关闭的时候点击程序里的关闭窗口,
关闭事件,先关闭所有对象(线程),再把窗体资源释放。
https://msdn.microsoft.com/en-us/library/system.windows.forms.form.close.aspx
When a form is closed, all resources created within the object are closed and the form is disposed. You can prevent the closing of a form at run time by handling theClosing event and setting the Cancel property of the CancelEventArgs passed as a parameter to your event handler. If the form you are closing is the startup form of your application, your application ends.
The two conditions when a form is not disposed on Close is when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Dispose manually to mark all of the form's controls for garbage collection.
效果图
Form.cs 主界面逻辑
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Threading; 10 using System.Xml; 11 using System.Xml.Linq; 12 using networkListener; 13 14 namespace WindowsFormsApplication1 15 { 16 public partial class Form1 : Form 17 { 18 //循坏秒数 19 static int scanSecond = 20; 20 21 //存储ip的数组 22 public static String[] ips = null; 23 24 //每个线程处理ip数目 25 public static int dealNum = 10; 26 27 //ip信息DataTable 28 DataTable infoDt = null; 29 30 DateTime beginTime ; 31 32 DateTime endTime ; 33 34 LogDAL logDAL ; 35 36 List<NetThread> threadList; 37 38 public Form1() 39 { 40 InitializeComponent(); 41 42 logDAL = new LogDAL(); 43 44 threadList = new List<NetThread>(); 45 46 //ip信息表初始化 47 infoDt = new DataTable(); 48 infoDt.Columns.Add(new DataColumn("名字")); 49 infoDt.Columns.Add(new DataColumn("ip地址")); 50 51 //数据初始化 52 threadNumText.Text = dealNum + ""; 53 scanSecondText.Text = scanSecond + ""; 54 55 //timer初始化 56 timer1.Interval = scanSecond * 1000; 57 timer1.Stop(); 58 } 59 60 /// <summary> 61 /// 准备需要迭代ip数据 62 /// </summary> 63 private void preparaData() 64 { 65 showMsg("读取ip.xml文件中!"); 66 //读取ip.xml文件 67 XElement xe = XElement.Load("ip.xml"); 68 //@"..\..\ip.xml" 对于输出目录 69 70 //直接找到元素为ip的这个结点,然后遍历读取所有的结果. 71 IEnumerable<XElement> elements = from adress in xe.Elements("ip") 72 select adress; 73 showInfo(elements); 74 75 } 76 77 /// <summary> 78 /// 迭代XML中所有ip节点 79 /// </summary> 80 /// <param name="elements">ip节点集合</param> 81 private void showInfo(IEnumerable<XElement> elements) 82 { 83 String name; 84 String ip; 85 int size = elements.Count(); 86 ips = new String[size]; 87 88 infoDt.Clear(); 89 90 //迭代出节点的数据 91 int i = 0; 92 foreach (var ele in elements) 93 { 94 name = ele.Element("name").Value; 95 ip = ele.Element("adress").Value; 96 infoDt.Rows.Add(new object[] { name, ip }); 97 ips[i] = ip; 98 i++; 99 } 100 101 //数据绑定到表 102 infoDataGrid.DataSource = infoDt; 103 104 } 105 106 /// <summary> 107 /// 刷新日志文件读取 108 /// </summary> 109 private void refreshLog() 110 { 111 112 DataSet ds = logDAL.GetList("", "LOG_NETLISTEN", "ROWNUM <= 200", "CREATE_TIME DESC"); 113 DataTable dt=ds.Tables[0]; 114 //数据绑定到表 115 logDataGrid.DataSource = dt; 116 logDataGrid.Columns[3].DefaultCellStyle.Format = "yyyy-MM-dd HH:mm:ss "; 117 logDataGrid.Refresh(); 118 } 119 120 /// <summary> 121 /// 启动按钮时间 122 /// </summary> 123 /// <param name="sender"></param> 124 /// <param name="e"></param> 125 private void startButton_Click(object sender, EventArgs e) 126 { 127 showMsg("程序成功启动!"); 128 startButton.Enabled = false; 129 modifyButton.Enabled = false; 130 131 //准备ip数据 132 preparaData(); 133 showMsg("ip数初始化完毕!"); 134 135 netScan(); 136 timer1.Start(); 137 } 138 139 /// <summary> 140 /// 添加消息 141 /// </summary> 142 /// <param name="message">消息</param> 143 public void showMsg(String message) { 144 this.msgTextBox.AppendText(message + System.Environment.NewLine); 145 } 146 147 /// <summary> 148 /// timer每隔一段时间自动调用 149 /// </summary> 150 /// <param name="sender"></param> 151 /// <param name="e"></param> 152 private void timer1_Tick(object sender, EventArgs e) 153 { 154 netScan(); 155 } 156 157 /// <summary> 158 /// 多线程监控网络 159 /// </summary> 160 private void netScan() { 161 showMsg("多线程监控网络开始"); 162 beginTime = System.DateTime.Now; 163 //启动网络监听多线程 164 for (int i = 0; i < ips.Length; i += dealNum) 165 { 166 new NetThread(i).start(); 167 } 168 169 endTime = System.DateTime.Now; 170 171 showMsg("耗时:"+(endTime-beginTime)); 172 showMsg("多线程监控网络结束"); 173 174 refreshLog();//刷新日志文件 175 showMsg("更新日志文件"); 176 showMsg("====================="); 177 } 178 179 private void modifyButton_Click(object sender, EventArgs e) 180 { 181 threadNumText.Text = dealNum + ""; 182 scanSecondText.Text = scanSecond + ""; 183 dealNum = Convert.ToInt16(threadNumText.Text); 184 scanSecond = Convert.ToInt16(scanSecondText.Text); 185 } 186 187 188 189 } 190 }
LogDAL.cs 操作数据库
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using SysDev.Utility.Data; 6 using SysDev.Utility.Security; 7 using System.Configuration; 8 using System.Data; 9 10 namespace WindowsFormsApplication1 11 { 12 class LogDAL 13 { 14 /// <summary> 15 /// 返回本项目默认数据库连接串 16 /// </summary> 17 /// <returns></returns> 18 public string GetDefaultConn() 19 { 20 return Security.Decrypt(ConfigurationManager.AppSettings["NetListenConn"]); 21 } 22 23 /// <summary> 24 /// 构造主列表SQL语句 25 /// </summary> 26 /// <param name="columnString">显示列</param> 27 /// <param name="filterString">筛选条件</param> 28 /// <param name="orderbyString">排序条件</param> 29 /// <returns>SQL执行语句</returns> 30 private string CreateSqlList(string columnString, string tableName, string filterString, string orderbyString) 31 { 32 StringBuilder cmdText = new StringBuilder(); 33 if (columnString == "") 34 cmdText.Append("select * from " + tableName); //默认全显示 sys_binding 35 else 36 cmdText.Append("select " + columnString + " from " + tableName + " "); 37 38 if (filterString.Trim() != "") 39 cmdText.Append(" where " + filterString); 40 41 if (orderbyString.Trim() != "") 42 cmdText.Append(" order by " + orderbyString); 43 else 44 cmdText.Append(" order by ID"); //默认按主键倒序 45 46 return cmdText.ToString(); 47 } 48 49 /// <summary> 50 /// 返回数据列表 51 /// </summary> 52 /// <param name="columnString">显示列</param> 53 /// <param name="filterString">筛选条件</param> 54 /// <param name="orderbyString">排序条件</param> 55 /// <returns></returns> 56 public DataSet GetList(string columnString, string tableName, string filterString, string orderbyString) 57 { 58 string sqlString = this.CreateSqlList(columnString, tableName, filterString, orderbyString); 59 return ORAHelper.Query(sqlString, GetDefaultConn()); 60 } 61 62 63 64 /// <summary> 65 /// 添加绑定信息 66 /// </summary> 67 /// <param name="sys_id">系统编号</param> 68 /// <param name="oper_no">主工号</param> 69 /// <param name="oper_no_binding">绑定的分工号</param> 70 public void Add(string log_ip, string log_msg) 71 { 72 ORAHelper.ExecuteSql("insert into LOG_NETLISTEN (LOG_ID,SERVER_IP,ERROR_MSG) " + 73 "values(seq_log.nextval,'" + log_ip + "','" + log_msg + "')", GetDefaultConn()); 74 } 75 76 } 77 }
NetThread.cs 线程逻辑
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Net.NetworkInformation; 7 using WindowsFormsApplication1; 8 using System.Data; 9 using System.Xml; 10 using System.Xml.Linq; 11 12 namespace networkListener 13 { 14 class NetThread 15 { 16 //线程 17 Thread thread = null; 18 19 //ping工具 20 Ping ping = new Ping(); 21 22 //ping响应结果 23 PingReply pingReply = null; 24 25 //扫描的起始下标 (包含) 26 int beginIndex ; 27 28 //扫描的终止下标(不包含) 29 int endIndex; 30 31 LogDAL logDAL; 32 33 /// <summary> 34 /// NetThread构造方法,用于传入beginIndex 35 /// </summary> 36 /// <param name="beginIndex">线程处理的起始下表</param> 37 public NetThread(int beginIndex) { 38 this.beginIndex = beginIndex; 39 this.endIndex = beginIndex + Form1.dealNum; 40 logDAL = new LogDAL(); 41 } 42 43 /// <summary> 44 /// 线程的主逻辑业务 45 /// </summary> 46 public void run() { 47 48 //endIndex 大于ip数目时候 49 if (endIndex > Form1.ips.Length) 50 { 51 endIndex = Form1.ips.Length; 52 } 53 54 55 for (int i = beginIndex; i < endIndex; i++) 56 { 57 //ip响应结果 58 pingReply = ping.Send(Form1.ips[i]); 59 60 //ping的通 61 if (pingReply.Status == IPStatus.Success) 62 { 63 //success 64 } 65 else 66 { //fail 67 logDAL.Add(Form1.ips[i], "" + pingReply.Status); 68 } 69 } 70 71 } 72 73 /// <summary> 74 /// 用于启动线程 75 /// </summary> 76 public void start() { 77 if (thread == null) { 78 thread = new Thread(run); 79 } 80 thread.Start(); 81 } 82 83 public void disposeTest() { 84 thread.DisableComObjectEagerCleanup(); 85 if (thread!=null) 86 { 87 thread = null; 88 } 89 } 90 91 } 92 }