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

原文地址:https://www.cnblogs.com/subendong/p/11822937.html

时间: 2024-10-16 08:41:57

c# 创建socket连接辅助类-可指定超时时间的相关文章

c# 创建socket连接辅助类

using AD.SocketForm.Model; using NLog; using System; using System.Net; using System.Net.Sockets; namespace AD.SocketForm.Service { public class SocketService { private Logger _logger = LogManager.GetCurrentClassLogger(); /// <summary> /// 创建socket /

mongodb建立索引时如何指定超时时间

mongodb自从2.2版本起为索引建立了TTL(time to live),可以指定一个类型为日期的字段为文档的索引并指定TTL(以秒为单位),mongodb内部每分钟执行一次检查TTL,如果超时则删除指定的文档,该特性用来实现session很适合. 使用java创建索引时,使用如下 //col为collection对象 BasicDBObject index = new BasicDBObject(); //_lastm为Date类型数据 index.put("_latm", 1)

Http和Socket连接区别

1.TCP连接 要想明白Socket连接,先要明白TCP连接.手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上. 建立起一个TCP连接需要经过“三次握手”: 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k

Exchange调整入站SMTP连接超时时间

双方邮件服务器在通过SMTP传送邮件的过程中,由于网络/带宽问题,或是邮件太大:花费的传递时间总会超过Exchange服务器SMTP连接限制的最大超时时间,最终导致邮件接受失败. 1.打开Exchange Management Shell窗口,先查看当前默认接收连接器的超时时间,假设默认接收连接器的名称为:Default EXCHANGE2010 Get-ReceiveConnector -Identity "Default EXCHANGE2010" |FL 可以看到Connecti

timeout Timeout时间已到.在操作完成之前超时时间已过或服务器未响应

Timeout时间已到.在操作完成之前超时时间已过或服务器未响应 问题 在使用asp.net开发的应用程序查询数据的时候,遇到页面请求时间过长且返回"Timeout时间已到.在操作完成之间超时时间已过或服务器未响应"的情况 分析 造成这一问题的原因大概有以下几点:     1.Asp.net请求超时         2.Webservice请求超时          3.IIS请求超时          4.数据库连接超时 凭经验判断,应当是数据库连接超时造成,根据在网上找到的解决方法

C# 给某个方法设定执行超时时间 C#函数运行超时则终止执行(任意参数类型及参数个数通用版)

在某些情况下(例如通过网络访问数据),常常不希望程序卡住而占用太多时间以至于造成界面假死. 在这时.我们可以通过Thread.Thread + Invoke(UI)或者是 delegate.BeginInvoke 来避免界面假死, 但是这样做时,某些代码或者是某个方法的执行超时的时间还是无法操控的.那么我们又是否有一种比较通用的方法.来设定某一个方法的执行超时的时间,让该其一旦超过指定时间则跳出指定方法.进而继续向下执行呢? 答案当然是肯定的. delegate.BeginInvoke可以实现代

C# 给某个方法设定执行超时时间

在某些情况下(例如通过网络访问数据),常常不希望程序卡住而占用太多时间以至于造成界面假死. 在这时.我们可以通过Thread.Thread + Invoke(UI)或者是 delegate.BeginInvoke 来避免界面假死, 但是这样做时,某些代码或者是某个方法的执行超时的时间还是无法操控的.那么我们又是否有一种比较通用的方法.来设定某一个方法的执行超时的时间,让其一旦超过指定时间则跳出指定方法.进而继续向下执行呢? 答案当然是肯定的. delegate.BeginInvoke可以实现代码

C# Socket连接请求超时机制

作者:RazanPaul 译者:Todd Wei 原文:http://www.codeproject.com/KB/IP/TimeOutSocket.aspx 介绍 您可能注意到了,.Net的System.Net.Sockets.TcpClient和System.Net.Sockets.Socket都没有直接为Connect/BeginConnect提供超时控制机制.因此,当服务器未处于监听状态,或者发生网络故障时,客户端连接请求会被迫等待很长一段时间,直到抛出异常.默认的等待时间长达20~30

DBLink创建 ORA-12154: TNS: 无法解析指定的连接标识符

因为对oracle不了解,这个问题可TM的搞了好久! 走的弯路: 1. 在客服端的PLSQL连接工具上折腾,而不是在服务器的PLSQL解决 2. 配置的tnsnames.org文件在环境变量path(oracle服务器)中指定的(PLSQL客服端的环境变量并没有指向该文件位置而是oracle的连接相关文件,但该文件的路径又是在哪儿指定的呢?迷茫中...) 3. 线下测试环境中,DBlink创建时,数据库(host)写的服务器的配置节点名称还是客服端的配置节点名称?但是线下写成orcl(客服端pl