蛙蛙池塘  
人生价值的最好体现就是做好本职工作...
公告
  • 残荷听雨,梨花飞雪,落英缤纷时节。晓来谁染枫林醉?点点都是离人泪
    活着,就是快乐!自信,就是美丽! 有人爱,就是幸福。
    春天来了
    但愿野百合也有春天

    第三季度的计划



    木了
    怎么抓w3wp的dump? 10-11 14:36
日历
<2007年12月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345
统计
  • 随笔 - 195
  • 文章 - 2
  • 评论 - 1783
  • 引用 - 68

导航

与我联系

搜索

 

常用链接

留言簿(45)

我参加的小组

我参与的团队

我的标签

随笔分类

随笔档案

相册

朋友

积分与排名

  • 积分 - 421115
  • 排名 - 51

最新评论

阅读排行榜

评论排行榜

60天内阅读排行

 

测试一
服务端

class Program
{
    
static void Main(string[] args)
    
{
        TcpChannel chan 
= new TcpChannel(8080);
        ChannelServices.RegisterChannel(chan,
false);
        RemotingConfiguration.RegisterWellKnownServiceType(
            
typeof(ServerObject),
            
"ServerObject", WellKnownObjectMode.Singleton);
        Console.WriteLine(
"server is start");
        Console.Read();
        chan.StopListening(
null);
        ChannelServices.UnregisterChannel(chan);
    }

}

public class ServerObject : MarshalByRefObject
{
    
public string SayHello(string name)
    
{
        Thread.Sleep(
5000);
        
return string.Format("Hello {0}", name);
    }

}


客户端

class Program
{
    
static void Main(string[] args)
    
{
        
try
        
{
            Hashtable props 
= new Hashtable();
            props[
"name"= "tcp_rem";
            props[
"timeout"= 1000;
            TcpChannel _tcpChannel 
= new TcpChannel(props, nullnull);
            ChannelServices.RegisterChannel(_tcpChannel, 
false);
            ServerObject so 
= (ServerObject)Activator.GetObject(typeof(ServerObject), "tcp://127.0.0.1:8080/ServerObject");
            Console.WriteLine(so.SayHello(
"onlytiancai"));
        }

        
catch (Exception ex)
        
{
            Console.WriteLine(ex);
        }

        Console.Read(); 
    }

}

一秒超时后客户端就会报以下错误
System.Net.Sockets.SocketException: 由于连接方在一段时间后没有正确答复或连接的主
机没有反应,连接尝试失败。
结论:tcpchannel的timeout设置对服务端处理时间过长时是起到超时作用的。

测试二
再做一个测试,把客户端连接的地址改成一个乱七八糟的远程地址。
ServerObject so = (ServerObject)Activator.GetObject(typeof(ServerObject), "tcp://192.192.192.192:8080/ServerObject");
这时候客户端会hang 10秒以上,也有可能hang更久。
结论:tcpchannel对连接网络慢或者网络层的执行时间太久是没有起到超时作用的。
测试三
再做一个测试,把我改进后的TcpClientTransportSink配置上,看看能不能起到超时的作用。
配置文件如下

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<system.runtime.remoting>
    
<application >
      
<channels>
        
<channel ref="tcp">
          
<clientProviders>
            
<formatter ref="binary"/>
            
<provider type="WawaSoft.Remoting.Channels.Tcp.TcpClientTransportSinkProvider,WawaRemoting" />
          
</clientProviders>
        
</channel>
      
</channels>
    
</application>
  
</system.runtime.remoting>
</configuration>

客户端代码如下

class Program
{
    
static void Main(string[] args)
    
{
        
try
        
{
            RemotingConfiguration.Configure(
"Client.exe.config"false);
            ServerObject so 
= (ServerObject)Activator.GetObject(typeof(ServerObject), "tcp://192.192.192.192:8080/ServerObject");
            Console.WriteLine(so.SayHello(
"onlytiancai"));
        }

        
catch (Exception ex)
        
{
            Console.WriteLine(ex);
        }

        Console.Read();
 
    }

}

一秒后出现如下错误提示
System.ApplicationException: connect timout

Server stack trace:
   在 WawaSoft.Remoting.Channels.RemoteConnection.CreateNewSocket(EndPoint ipEnd
Point) 位置 E:\huhao\project\RemotingTimeoutTest\WawaRemoting\Channels\RemoteCon
nection.cs:行号 89

结论:使用新的ClientTransportSink解决了因为网络问题hang太久的问题,但是目前的代码我只在connect上加了超时机制,send和receive还没有加超时机制,再有一个问题就是在同步调用上做超时必须另起个线程然后用join做超时,稳定性还得做压力测试来确认。

新的ClientTransportSink和测试代码见以下链接。
RemotingTimeoutTest.zip
以上代码大多都是反射与.net fx,所以稳定性应该还是很好的,只修改了RemoteConnection类的CreateNewSocket方法,如下
修改前

        private SocketHandler CreateNewSocket(EndPoint ipEndPoint)
        
{
            Socket socket 
= new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            
this.DisableNagleDelays(socket);
            socket.Connect(ipEndPoint);
            
this._lkgIPEndPoint = socket.RemoteEndPoint;
            
return this._socketCache.CreateSocketHandler(socket, this._machineAndPort);
        }

修改后

        
private SocketHandler CreateNewSocket(EndPoint ipEndPoint)
        
{
            Socket socket 
= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.Debug, 
1);
            Exception pingException 
= null;
            DateTime now 
= DateTime.Now;

            System.Threading.Thread pingThread 
= new System.Threading.Thread(
                
delegate()
                
{
                    
try
                    
{
                        socket.Connect(ipEndPoint);
                        
//这里不用beginConnect,太麻烦
                    }

                    
catch (Exception ex)
                    
{
                        pingException 
= ex;
                    }

                }
);

            pingThread.Start();
            
if (pingThread.Join(1000)){
                
if (pingException == null)
                
{
                    
return this._socketCache.CreateSocketHandler(socket, this._machineAndPort);
                }

                
else{throw pingException;}
            }

            
throw new ApplicationException("connect timout");
        }
改进;超时的部分想办法不用join事先,用一个waithandle实现。
posted on 2007-12-28 21:00 蛙蛙池塘 阅读(1694) 评论(8)  编辑 收藏 所属分类: 综合区
评论:
  • #1楼   iceboundrock       Posted @ 2007-12-28 21:31
    哥们儿,这么干太费劲了。你直接把getobject放到一个线程里面,然后用一个ManualResetEvent mre。放个mre.set在getobject后面,在主线程里面waitone,如果waitone返回false就是超时,否则就是正常的。   回复  引用  查看    

  • #2楼   gOODiDEA       Posted @ 2007-12-28 21:52
    直接修改配置,如:
    <channel ref="http" useDefaultCredentials="true" port="0" timeout="1000">   回复  引用  查看    

  • #3楼 [楼主]  蛙蛙池塘       Posted @ 2007-12-28 22:29
    @iceboundrock
    不行呀,大哥,getobject是不会hang的一般,那句一般都不会出错也。我抓的dump是在remoting内部调用后端服务的时候hang在socket.receive上了,有的时候hang了10几分钟,这个线程还拿着锁,后面线程池里一大群线程等着它释放锁,而且异步remoting貌似也是调用的socket的同步方法,而且我设置了TcpChannel的Timeout,还hang 10几分钟。所以只好扩展remoting的传输sink了。
    用waithandle能实现超时功能,不过也得另起线程,我觉得和join差不多。
    @gOODiDEA
    兄弟测试过吗?你有没有反射过那个timeout的代码是如何实现的?   回复  引用  查看    

  • #4楼   gOODiDEA       Posted @ 2007-12-29 08:20
    没有反射过,它相当于:

    RemotingConfiguration.Configure ( config, false );
    IRemoteSearchable remoteSearcher = ( IRemoteSearchable ) RemoteClientHelper.GetObject ( typeof ( IRemoteSearchable ) );
    IDictionary remoteSearcherProps = ChannelServices.GetChannelSinkProperties ( remoteSearcher );
    remoteSearcherProps ["timeout"] = 1000;   回复  引用  查看    

  • #5楼   反对方的反对 [未注册用户] Posted @ 2007-12-29 08:42
    学习中……,现在正在看这方面的书籍那。   回复  引用    

  • #6楼   iceboundrock       Posted @ 2007-12-29 09:21
    @蛙蛙池塘
    Orz,你不是说:测试二
    再做一个测试,把客户端连接的地址改成一个乱七八糟的远程地址。
    ServerObject so = (ServerObject)Activator.GetObject(typeof(ServerObject), "tcp://192.192.192.192:8080/ServerObject");
    这时候客户端会hang 10秒以上,也有可能hang更久。   回复  引用  查看    

  • #7楼 [楼主]  蛙蛙池塘       Posted @ 2007-12-29 09:34
    @iceboundrock
    是说改了这句,实际上是hang在调用方法上面,一般getobject之后要反复调用上面的方法的,我没说清楚,呵呵。
    @gOODiDEA
    我做的第一个测试不是设置了prop["timeout"]了吗?你说的应该只是以配置形式实现吧,而且你的配置好像根本就不对。
      回复  引用  查看    

  • #8楼   gOODiDEA       Posted @ 2007-12-29 13:14
    嗯,MS的文档里没提到,但可以用   回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)