作者:RazanPaul

译者:Todd Wei

原文:http://www.codeproject.com/KB/IP/TimeOutSocket.aspx

介绍

您可能注意到了,.Net的System.Net.Sockets.TcpClient和System.Net.Sockets.Socket都没有直接为Connect/BeginConnect提供超时控制机制。因此,当服务器未处于监听状态,或者发生网络故障时,客户端连接请求会被迫等待很长一段时间,直到抛出异常。默认的等待时间长达20~30s。.Net Socket库的SocketOptionName.SendTimeout提供了控制发送数据的超时时间,但并非本文讨论的连接请求的超时时间。

背景

这个问题最初源于我的某个项目,在解决以后,我曾将关键代码发表在自己的博客上。我注意到不少人对此表示感谢,所以我想这是一个常见的问题,或许很多人都需要解决它。

实现

下面是实现的关键代码:


class TimeOutSocket
{
    private static bool IsConnectionSuccessful = false;
    private static Exception socketexception;
    private static ManualResetEvent TimeoutObject = new ManualResetEvent(false);     public static TcpClient Connect(IPEndPoint remoteEndPoint, int timeoutMSec)
    {
        TimeoutObject.Reset();
        socketexception = null;           string serverip = Convert.ToString(remoteEndPoint.Address);
        int serverport = remoteEndPoint.Port;           
        TcpClient tcpclient = new TcpClient();
        
        tcpclient.BeginConnect(serverip, serverport, 
            new AsyncCallback(CallBackMethod), tcpclient);         if (TimeoutObject.WaitOne(timeoutMSec, false))
        {
            if (IsConnectionSuccessful)
            {
                return tcpclient;
            }
            else
            {
                throw socketexception;
            }
        }
        else
        {
            tcpclient.Close();
            throw new TimeoutException("TimeOut Exception");
        }
    }
    private static void CallBackMethod(IAsyncResult asyncresult)
    {
        try
        {
            IsConnectionSuccessful = false;
            TcpClient tcpclient = asyncresult.AsyncState as TcpClient;
             
            if (tcpclient.Client != null)
            {
                tcpclient.EndConnect(asyncresult);
                IsConnectionSuccessful = true;
            }
        }
        catch (Exception ex)
        {
            IsConnectionSuccessful = false;
            socketexception = ex;
        }
        finally
        {
            TimeoutObject.Set();
        }
    }
}

这里,ManualResetEvent的WaitOne(TimeSpan, Boolean)起到了主要的作用。它将阻止当前线程,直到ManualResetEvent对象被Set或者超过timeout时间。上面的代码中,调用BeginConnect后通过WaitOne方法阻止当前线程,如果在timeoutMSec时间内连接成功,将在CallBackMethod回调中调用TimeoutObject.Set,解除被阻塞的连接线程并返回;否则,连接线程会在等待超时后,主动关闭连接并抛出TimeoutException。

总结

虽然实现非常简单,但或许很多人都需要连接请求超时机制,如果有任何问题,我会尽力为您解答。

C# Socket连接请求超时机制的更多相关文章

  1. C# Socket.Connect连接请求超时机制

    介绍 您可能注意到了,.Net的System.Net.Sockets.TcpClient和System.Net.Sockets.Socket都没有直接为Connect/BeginConnect提供超时 ...

  2. 异步和同步http请求超时机制

    异步超时设置: 例子: Example: do a simple HTTP GET request for http://www.nethype.de/ and print the response ...

  3. socket测试远程地址能否连接并为连接设置超时

    public class TestConnect { string hostIp = ""; ; public string recMsg = ""; Sock ...

  4. socket测试远程地址能否连接并为连接设置超时(转)

    public   class TestConnect { string hostIp = ""; int port = 3314; public string recMsg = & ...

  5. 从报错“无效操作,连接被关闭”探究Transaction的Timeout超时机制

    1.报错如下:Invalid Operation the connection is closed,无效操作,连接被关闭.这个错误是并不是每次都报,只有在复杂操作.大事务的情况下才偶然报出来. sta ...

  6. C# Socket连接超时设置

    问题描述:         对于C# Socket没有超时设置的选项,默认情况下进行Socket连接,返回连接失败需要20-30s时间,严重影响用户体验 问题解决: Socket服务器端: Socke ...

  7. 一个Socket连接管理池(心跳机制)

    一个Socket连接管理池(心跳机制) http://cuisuqiang.iteye.com/blog/1489661

  8. ES transport client底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync或者await(future超时机制)来实现类似同步调用!因此,ES transport client可以同步调用也可以异步(不过底层的socket必然是异步实现)

    ES transport client底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync或者await(future超时机制)来实现类似同步调用! 因此,ES tra ...

  9. c# 创建socket连接辅助类-可指定超时时间

    using AD.SocketForm.Model; using NLog; using System; using System.Net.Sockets; using System.Threadin ...

随机推荐

  1. page80-栈用例-算术表达式求值

    表达式由括号, 运算符和操作数(数字)组成.我们根据以下4中情况从左到右逐个将这些实体送入栈处理. (1)将操作数压入操作数栈: (2)将运算符压入运算符栈: (3)忽略左括号: (4)在遇到右括号时 ...

  2. 关于Java中获取当前系统时间

    一. 获取当前系统时间和日期并格式化输出: import java.util.Date; import java.text.SimpleDateFormat; public class NowStri ...

  3. 使用JDBC-ODBC读取Excel文件

    以下代码我没有真正去实践,紧做为总结,方便以后查阅: 这种方法需要设置ODBC源..... 参考: http://xytang.blogspot.com/2008/02/how-to-connect- ...

  4. MyFragment

    手机横竖屏自动切换不同的View: Landscape-Horizontal-横屏 Portrait-Vertical-竖屏 package com.example.shad_fnst.myfragm ...

  5. SQL 存储过程 执行效率优化提升 (显示估计)

    在sql server 查询区 通过执行 "显示估计的执行计划" ,可以给出 存储过程 缺少索引的提示,并自动生成建立相应 索引 的代码 显示估计的执行计划 执行结果提示: 哦,算 ...

  6. 北大ACM(POJ1010-STAMPS)

    Question:http://poj.org/problem?id=1010问题点:DFS.剪枝. Memory: 220K Time: 32MS Language: C++ Result: Acc ...

  7. Ubuntu14.04 Chromium 编译

    1.下载depot_tools: 首先安装 git-core: sudo apt-get install git-core 执行命令: git clone https://chromium.googl ...

  8. SQL Server 事务处理 回滚事务

    --创建表: GO CREATE TABLE [dbo].[tb1]( [Id] [int] NOT NULL, [c1] [nvarchar](50) NULL, [c2] [datetime] N ...

  9. 读书笔记-UIView与控件

    1.UIView 在Objective-C中,NSObject是所有类的“根”类.同样,在UIKit框架中,也存在一个如此神奇的类UIView.从继承关系上看,UIView是所有视图的根. 1.1.U ...

  10. 20141212--C#对象比较

    static void Main(string[] args) { Class2 oo = new Class2(); oo.shu = ; oo.zi = "你"; Class2 ...