当前做一个数据采集温度湿度噪音的项目, 一如既往的按照互联网公司的做法,起一个c#mvc的项目, 概括来说c#的mvc 比java spring mvc 感觉简洁了很多,本人曾在几年前从winform 直接跳到了java sringmvc ,光配置都自己摸索了一阵子
当前公司用的asp.net 技术,于是乎又熟练了一下c#的mvc , 第一就是编辑器方面建一个项目很简单,配置就三几步,不像eclipse 的各种的配置啊.逻辑没写多少,配置先耽误一段时间.
回到主题, 采集数据采用udp的传输方式, 硬件那边据说是为了省电,于是乎我把udpserver 建到了mvc的项目中了,开始了一连串的调试
打开软件启动udpserver 需在Global.asax 内添加启动.我的理解是 mvc 没有 static void Main() 入口,在global中设置 RunUdpServer.Run(); //启动服务
最开始是从网页中启动的服务, 服务启动之后,在一段时间内没有请求,或者是10分钟, udpserver 出现无反应,链接断开,最开始判断是udpport 那个服务组件的版权问题, 现在看看不是应该人家组件版权问题,
于是乎,udpport 不行,找了另一个换上 ,本来觉得应该问题解决,后来又出现10分钟左右掉链子. 在那时,隔一段时间打开首页时没有连续打开的速度快,我感觉iis 有个慵懒机制,没有请求时估计服务都挂起了,要不为何第一次请求index 反应了一段时间.
到现在不能确定iis问题,因为毕竟websocket 也是tcp类似的东西在上边跑着没问题的..此时想到,mvc上启动udp server应该是行不通, mvc 提供的是http服务器, udp 也是个比http 甚至还低一层的协议,从应用分工的角度上看,应该单拿出来才对,用c# winform 实现udpserver ,mvc那块就提供网页展示查询就可以了.
开始从github上找udpserver , 关键词搜索也很重要,不带winform 出来的没有一个想要的
很多都是老一套接收数据时写个死循环,循环接收,难道不知道有那种事件接收的方式吗,(因为我看过netty 里边似乎就是监听端口,来了事件的方式通知的,这种方式消息很及时了)
while (true) { byte[] data = new byte[1024]; int length = 0; try { length = udpServer.ReceiveFrom(data, ref Remote);//接受来自服务器的数据 } ............}
后来找到了
UdpClient-master
https://github.com/we-ciao/UdpClient
微软给我们提供了一个udpclient ,看看这个类,里边已经写好了接收事件, 我也发现网上有的代码中,也用了udpclient, 里边还是带了个while(true){}生搬硬套上的吧
这套源码经过测试,在本机上发本机是没问题的,有个问题就是在服务器上返回不到请求端,后来发现是源码启动了两个udpclient ,接收和发送用的不是同一个
这在公网上是有问题的
再后来发现上边的写法是正确的 while(true) 并不是死循循环,应该是socket.ReceiveFrom(buffer, ref endPointReceive); 跑到此函数之后,挂起了,在次函数下边加断点,除非有新数据,程序是运行不到的
第二, 事件接收是用于客户端接收事件的,套用到服务器端不好用
第三:udpclient 这个类不好用,在局域网内相互能测通,换到内网A 到B公网 ,B能收到A发的信息紧接着给A返回信息,A是接收不到的,这个问题一直没找到好的解决法子,网上千篇一律是在内网测试的例子,我的也通了换到公网就出问题
第四:彻底抛弃udpclient这个类 直接使用socket
class Server { static void Main(string[] args) { var ipAddress = IPAddress.Parse("127.0.0.1"); // Your IP Address var port = 27001; using (var socket = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { var endPoint = new IPEndPoint(ipAddress, port); socket.Bind(endPoint); var length = 0; var buffer = new byte[66000]; List<byte> byteList = new List<byte>(); EndPoint endPointReceive = new IPEndPoint(IPAddress.Any, 0); try { int temp = 0; while (true) { Console.WriteLine("Waiting..."); length = socket.ReceiveFrom(buffer, ref endPointReceive); Console.WriteLine($"length: {length}"); byte[] a = new byte[] { 0x30, 0x31 }; socket.SendTo(a, endPointReceive); for (int i = 0; i < length; i++) { byteList.Add(buffer[i]); } temp++; if (temp == 2) break; } } catch (Exception ex) { Console.WriteLine(ex.Message); Console.ReadLine(); } Console.WriteLine("list count: " + byteList.Count); // File writed FileStream fs = File.Create("uno.jpeg"); fs.Write(byteList.ToArray()); socket.Shutdown(SocketShutdown.Both); socket.Close(); Console.WriteLine("End"); Console.ReadLine(); } } }
上边代码中,客户端发送给服务器端,收到信息后,直接返回,是没有问题的.
经过几个版本的测试,问题总算是解决了.
资料: iis 的应用回收是不是导致udpserver 被关掉,在下边可以做个参考
最近在做一个项目,需要在程序中定时不断的执行某些操作,结果发现每天7,8点过后到第二天9点,定时程序经常都没有在执行,后来才知道由于IIS的应用池回收导致Application停止,而这段时间又没有人再次访问网站,结果在Application_Start中的定时执行程序代码就没有再执行,在网上搜索一番,找到了解决办法,现和大家一起分享交流,原理就是在应用程序结束时发出一个Web请求访问网站,启动Application_Start。 void Application_End(object sender, EventArgs e) { // 在应用程序关闭时运行的代码 //解决应用池回收问题 System.Threading.Thread.Sleep(5000); string strUrl = "网站地址"; System.Net.HttpWebRequest _HttpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(strUrl); System.Net.HttpWebResponse _HttpWebResponse = (System.Net.HttpWebResponse)_HttpWebRequest.GetResponse(); System.IO.Stream _Stream = _HttpWebResponse.GetResponseStream();//得到回写的字节流 }