zoukankan      html  css  js  c++  java
  • 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的状态,无需考虑线程同步。因为这个辅助类实例化后,是被驻留在内存里面的,有可能会被多次使用。为了线程安全,所以写在了里面。

  • 相关阅读:
    Animation(三)
    布局
    AutoCommpleteText
    PHP数组中常用函数
    Animation(四)
    转:JAVA内存映射文件
    Ubuntu安装jdk
    转:Java NIO 详解
    转:长连接与短连接
    Direct or Nondirect ByteBuffer
  • 原文地址:https://www.cnblogs.com/subendong/p/11822937.html
Copyright © 2011-2022 走看看