Socket .net MVC 的配置 包括异常断开

解决问题: 1. Socket 的异常断开 

     2. 部署在IIS程序池上的程序回收导致 端口占用,对象资源却已经释放的BUG

    

SocketHelper 类   inOptionValues .net框架中用于检测连接的客户端 检测时间(默认2小时)   或者自己写个心跳包(客户端和服务端用规定协议)   

  1         #region 变量
  2 
  3         //服务器监听socket 
  4         public static Socket listener = null;
  5 
  6         /// <summary>
  7         /// 连接列表
  8         /// </summary>
  9         public static List<Socket> socketList = new List<Socket>();
 10 
 11         public static Thread listenClientThread = null;
 12 
 13         private static byte[] inOptionValues = null;
 14 
 15         #endregion
 16 
 17 
 18 
 19         #region 开启监听 (接收数据)
 20 
 21         /// <summary>
 22         /// 开启监听
 23         /// </summary>
 24         public static void StartListening()
 25         {
 26             uint dummy = 0;
 27             inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
 28             BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0); //是否启用Keep-Alive
 29             BitConverter.GetBytes((uint)30000).CopyTo(inOptionValues, Marshal.SizeOf(dummy)); //检测客户端时间周期
 30             BitConverter.GetBytes((uint)2000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2); //失败后连续探测时间
 31 
 32             byte[] bytes = new Byte[1024];
 33             //首先是构造一个socket对象
 34             IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
 35             IPAddress ip = null;
 36             foreach (var item in ipHostInfo.AddressList)
 37             {
 38                 if (item.AddressFamily == AddressFamily.InterNetwork)
 39                 {
 40                     ip = item;
 41                     break;
 42                 }
 43             }
 44             IPAddress ipAddress = ipHostInfo.AddressList[0];
 45             //System.Web.HttpContext.Current.A
 46             IPEndPoint localEndPoint = new IPEndPoint(ip, int.Parse(System.Configuration.ConfigurationManager.AppSettings["Port"]));
 47             listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 48             try
 49             {
 50                 listener.Bind(localEndPoint);
 51                 listener.Listen(100);//开始监听
 52 
 53                 while (true)
 54                 {
 55                     // 接收请求连接,handler接收该连接,之后使用handler处理收发数据的问题
 56                     Socket handler = listener.Accept();
 57                     handler.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
 58 
 59                     IPEndPoint clientipe = (IPEndPoint)handler.RemoteEndPoint;
 60                     //SetServerLog("*******" + handler.RemoteEndPoint + "已连接服务器,正在监听!********");
 61                     //SetConnectList(handler.RemoteEndPoint.ToString(), true);
 62 
 63                     Thread nowThread = new Thread(new ParameterizedThreadStart(ReceiveClientData));
 64                     nowThread.IsBackground = true;
 65                     nowThread.Name = handler.RemoteEndPoint.ToString();
 66 
 67                     Socket sk = new Socket();
 68 
 69                     //加入socket列表
 70                     socketList.Add(sk);
 71 
 72                     nowThread.Start(handler);
 73                 }
 74             }
 75             catch (Exception e)
 76             {
 77                 //释放资源  IIS回收  正常断开的异常
 78                 if (e.Message != "一个封锁操作被对 WSACancelBlockingCall 的调用中断。")
 79                     throw e;
 80                 else
 81                     throw e;
 82             }
 83         }
 84 
 85         //public delegate void CallBack();
 86 
 87         // 接受 客户端的信息
 88         private static void ReceiveClientData(object client)
 89         {
 90             Socket nowClient = (Socket)client;
 91             while (true)
 92             {
 93                 try
 94                 {
 95                     int res = 0;
 96                     byte[] bytes = new byte[1024];
 97                     // 不断的接受客户端发来的信息, 当客户端离线后,退出。
 98                     res = nowClient.Receive(bytes);
 99 
100                     if (res <= 0)
101                     {
102                         throw new SocketException();
103                     }
104 
105                     string str = Encoding.UTF8.GetString(bytes, 0, res);
106 
107                     //绑定ID  业务逻辑 
108                     if (str.IndexOf("****:****") >= 0)
109                     {
110                         foreach (var item in socketList)
111                         {
112                             if (item.RemoteEndPoint == nowClient.RemoteEndPoint)
113                             {
114                                 SendMsg(item.RemoteEndPoint,"SET:(1,2,3)");
115                                 break;
116                             }
117                         }
118                     }
119                 }
120                 catch (SocketException se)
121                 {
122                     socketList = (from si in socketList where si.RemoteEndPoint != nowClient.RemoteEndPoint select si).ToList();
123                     nowClient.Close();
124                     break;
125                 }
126                 catch (Exception ee)
127                 {
128                     throw ee;
129                 }
130             }
131         }
132 
133         #endregion
134 
135         #region 发送数据
136 
137         /// <summary>
138         /// 发送数据给客户端
139         /// </summary>
140         /// <param name="ep">ip和Port</param>
141         /// <param name="msg">发送的消息</param>
142         public static void SendMsg(EndPoint ep, string msg)
143         {
144             try
145             {
146                 foreach (var item in socketList)
147                 {
148                     if (item.listener.RemoteEndPoint == ep)
149                     {
150                         byte[] data = Encoding.UTF8.GetBytes(msg);
151                         item.listener.Send(data);
152                         break;
153                     }
154                 }
155             }
156             catch (Exception ee)
157             {
158                 throw ee;
159             }
160         }
161 
162 
163         #endregion
View Code

 

Global 里设置    Application_End 函数中 释放资源

 1         protected void Application_Start()
 2         {
 3 
 4             if (SocketHelper.listenClientThread == null)
 5             {
 6                 SocketHelper.listenClientThread = new Thread(new ThreadStart(SocketHelper.StartListening));
 7                 SocketHelper.listenClientThread.IsBackground = true;
 8                 SocketHelper.listenClientThread.Start();
 9             }
10 
11             AreaRegistration.RegisterAllAreas();
12             RegisterGlobalFilters(GlobalFilters.Filters);
13             RegisterRoutes(RouteTable.Routes);
14         }
15 
16         protected void Application_End()
17         {
18             SocketHelper.listener.Close();
19             SocketHelper.listener.Dispose();
20             SocketHelper.listenClientThread = null;
21         }
View Code

 

欢迎提出问题 谢谢~~

posted @ 2015-03-16 13:57  执着的码农  阅读(664)  评论(0编辑  收藏  举报