解决问题: 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
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 }
有细节上稍许不对 欢迎提出问题 谢谢~~
时间: 2024-10-14 20:16:44