c# 创建socket连接辅助类-可指定超时时间
using AD.SocketForm.Model; using NLog; using System; using System.Net.Sockets; using System.Threading; namespace AD.SocketForm.Service { /// <summary> /// Socket连接类-可指定超时时间 /// 参考网址://www.cnblogs.com/weidagang2046/archive/2009/02/07/1385977.html /// </summary> public class SocketNewService { private Logger _logger = LogManager.GetCurrentClassLogger(); /// <summary> /// 连接socket /// </summary> /// <param name="model"></param> /// <param name="timeout">单位:毫秒</param> /// <returns></returns> public Socket Create(HubModel model, int timeout) { var isConnected = false; var manualResetEvent = new ManualResetEvent(false); var tcpClient = new TcpClient(); #region 异步方法委托 Action<IAsyncResult> action = (asyncresult) => { try { TcpClient tcpclient = asyncresult.AsyncState as TcpClient; if (tcpclient.Client != null) { tcpclient.EndConnect(asyncresult); isConnected = true; } //Thread.Sleep(1000); } catch (Exception ex) { _logger.Error(string.Format("获取socket异常,message:{0},stacktrace:{1}", ex.Message, ex.StackTrace)); isConnected = false; } finally { manualResetEvent.Set(); } }; #endregion tcpClient.BeginConnect(model.IP, model.Port, new AsyncCallback(action), tcpClient); //判断在指定的时间以内是否收到释放锁的通知 if (manualResetEvent.WaitOne(timeout, false)) { //Console.WriteLine("连接成功"); if (isConnected) { return tcpClient.Client; } else { return null; } } else { //Console.WriteLine("超时"); tcpClient.Close(); return null; } } /// <summary> /// 关闭socket /// </summary> /// <param name="socket"></param> public void Close(Socket socket) { if (socket != null) { socket.Close(); socket = null; } } /// <summary> /// 判断Socket是否已连接 /// </summary> /// <param name="socket"></param> /// <returns></returns> public bool IsConnected(Socket socket) { if (socket == null || socket.Connected == false) { return false; } bool blockingState = socket.Blocking; try { byte[] tmp = new byte[1]; socket.Blocking = false; socket.Send(tmp, 0, 0); return true; } catch (SocketException e) { // 产生 10035 == WSAEWOULDBLOCK 错误,说明被阻止了,但是还是连接的 if (e.NativeErrorCode.Equals(10035)) { return true; } else { return false; } } catch (Exception ex) { _logger.Error(string.Format("检查Socket是否可连接时异常,message:{0},stacktrace:{1}", ex.Message, ex.StackTrace)); return false; } finally { socket.Blocking = blockingState; // 恢复状态 } } } }
主要是通过两点:
1、通过if (manualResetEvent.WaitOne(timeout, false))来处理。它的作用是:阻止当前线程N毫秒,期间如果有调用manualResetEvent.Set()立即取消当前线程的阻塞,并且返回true;如果没有调用,时间到了后依然取消当前线程的阻塞,但是返回false。
2、通过tcpClient.BeginConnect(model.IP, model.Port, new AsyncCallback(action), tcpClient)建立tcp连接。这句话的意思是以异步的方式建立tcp连接,成功之后调用指定的回调方法。即new AsyncCallback(action)。
另外,这个类把回调方法写在了Create方法里面,原因是方便处理isConnected的状态,无需考虑线程同步。因为这个辅助类实例化后,是被驻留在内存里面的,有可能会被多次使用。为了线程安全,所以写在了里面。